Files
Client/rylCoder_16.02.2008_src/CScriptParser.vb
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

477 lines
20 KiB
VB.net

'################################################
'## ##
'## RYL mcf & gsf file editor ##
'## ##
'## (C) 2006 & 2007 AlphA ##
'## ##
'## This source is for private development. ##
'## You can have this source only with the ##
'## owners permission. ##
'## ##
'################################################
Public Class CScriptParser
Private iFunctions As CMcfBase.SFunction() = {}
Private iTxtLines As String() = {}
Public RYLVersion As Integer = 0
Public RYLFileType As CMcfBase.EFileType = CMcfBase.EFileType.EUnknown
Private Shared iCulture As New System.Globalization.CultureInfo("en-US")
Public Shared hexNumbers As CheckState = CheckState.Indeterminate
Public LineFeed As String = vbLf
Public Function Struct2File(ByRef functions As CMcfBase.SFunction(), ByVal fileName As String) As Boolean
Try
Struct2TXT(functions)
Dim sW As New IO.StreamWriter(fileName, False)
For Each l As String In iTxtLines
sW.WriteLine(l)
Next
sW.Close()
Catch ex As Exception
MsgBox(ex.Message)
Return False
End Try
Return True
End Function
Public Sub Struct2TXT(ByRef functions As CMcfBase.SFunction())
iFunctions = functions
If iFunctions.Length < 1 Then
iTxtLines = New String() {"//////// Please Load a file in first ////////"}
Exit Sub
End If
Dim lS As New List(Of String)
lS.Add("///////////////////////////////////////")
lS.Add("//")
If RYLVersion > 0 Then lS.Add("// RYL " & RYLVersion & " " & CMcfBase.SFileType(RYLFileType) & "")
lS.Add("//")
lS.Add("////////////// Functions //////////////")
For Each f As CMcfBase.SFunction In iFunctions
If f.isExternal Then
Dim l As String = CMcfBase.DataTypeString(f.returnType) & " " & f.name & "("
If f.parameterTypes.Length > 0 Then
For Each p As CMcfBase.DataType In f.parameterTypes
l &= CMcfBase.DataTypeString(p) & ", "
Next
l = l.Substring(0, l.Length - 2)
End If
l &= ");"
lS.Add(l)
End If
Next
lS.Add("///////////////////////////////////////")
For Each f As CMcfBase.SFunction In iFunctions
If Not f.isExternal Then
If f.name <> "" Then 'Main function has no name
lS.Add("")
lS.Add("")
Dim l As String = CMcfBase.DataTypeString(f.returnType) & " " & f.name & "("
If f.parameterTypes.Length > 0 Then
For Each p As CMcfBase.DataType In f.parameterTypes
l &= CMcfBase.DataTypeString(p) & ", "
Next
l = l.Substring(0, l.Length - 2)
End If
l &= ")"
lS.Add(l)
lS.Add("{")
End If
For Each sL As CMcfBase.SScriptLine In f.data
Dim l As String = iFunctions(sL.callTo).name & "("
If sL.parameters.Length > 0 Then
For Each fp As CMcfBase.SParamElem In sL.parameters
Select Case fp.type
Case CMcfBase.DataType.EFloat
Dim tmp As Single = fp.value
l &= tmp.ToString(iCulture)
Case CMcfBase.DataType.EInteger
If hexNumbers = CheckState.Checked Then
l &= "0x" & Hex(fp.value)
ElseIf hexNumbers = CheckState.Indeterminate Then
l &= IIf(fp.value >= &HF00000, "0x" & Hex(fp.value), fp.value)
Else
l &= fp.value
End If
Case CMcfBase.DataType.EString
Dim tmp As String = fp.value
l &= ControlChars.Quote & tmp.Replace(ControlChars.Quote, "\" & ControlChars.Quote) & ControlChars.Quote
Case CMcfBase.DataType.EBool
l &= IIf(fp.value, "true", "false")
End Select
l &= ", "
Next
l = l.Substring(0, l.Length - 2)
End If
l &= ");"
lS.Add(addFormatting(l, iFunctions(sL.callTo)))
Next
If f.name <> "" Then lS.Add("}")
End If
Next
lS.Add("")
lS.Add("")
lS.Add("////////// Created on " & Now() & " by rylCoder ////////////")
iTxtLines = lS.ToArray()
End Sub
Public Function File2struct(ByVal fileName As String) As Boolean
Try
Dim sR As New IO.StreamReader(fileName)
Dim txt As String = sR.ReadToEnd
sR.Close()
TXT2struct(txt)
Catch ex As textException
MsgBox(ex.ToString & " on line " & (ex.row + 1) & " on pos " & (ex.position + 1))
Return False
Catch ex As Exception
MsgBox(ex.Message)
Return False
End Try
Return True
End Function
Public Shared Function detectLineFeed(ByRef txt As String) As String
If txt.IndexOf(vbNewLine, 0) >= 0 Then
Return vbNewLine
ElseIf txt.IndexOf(vbLf, 0) >= 0 Then
Return vbLf
End If
Return vbNewLine
End Function
Public Sub TXT2struct(ByRef txt As String)
LineFeed = detectLineFeed(txt)
TXT2struct(RemoveComments(txt).Split(LineFeed), False)
End Sub
Public Sub TXT2Struct(ByVal Lines As String(), Optional ByVal ParseComments As Boolean = True)
Dim orgText As String = String.Join(LineFeed, Lines)
If ParseComments Then Lines = RemoveComments(String.Join(LineFeed, Lines)).Split(LineFeed)
Dim badChars As Char() = {vbNewLine, vbCr, vbLf, vbTab}
Dim funcs As New List(Of CMcfBase.SFunction)
Dim funcData As New List(Of List(Of CMcfBase.SScriptLine))
' Main function definition
funcs.Add(CMcfBase.CreateMainFunction())
funcData.Add(New List(Of CMcfBase.SScriptLine))
Dim ongoingFunction As Integer = 0 'default is "main"
For index As Long = 0 To Lines.Length - 1
Dim line As String = Trim(Lines(index))
If line.IndexOfAny(badChars) >= 0 Then
For Each c As Char In badChars
line = line.Replace(c, "")
Next
line = line.Trim()
End If
If line.StartsWith("{") OrElse line.EndsWith("{") Then
ongoingFunction = funcs.Count - 1 'The last function that was added to the array
line = line.Trim("{"c)
End If
If line.StartsWith("}") OrElse line.EndsWith("}") Then
ongoingFunction = 0 'Set back to main
line = line.Trim("}"c)
End If
If line <> "" Then
Dim functionFound As Boolean = False
For Each sDataType As String In CMcfBase.DataTypeString
If line.StartsWith(sDataType & " ") Then
Try
funcs.Add(line2func(line, funcs.Count))
Catch ex As textException
ex.row = index + 1
ex.overallPos = orgText.IndexOf(Lines(index))
Throw
Catch ex As Exception
Dim ex2 As New textException(ex.Message, index + 1)
ex2.overallPos = orgText.IndexOf(Lines(index))
Throw ex2
End Try
funcData.Add(New List(Of CMcfBase.SScriptLine))
functionFound = True
Exit For
End If
Next
Try
If Not functionFound Then
funcData(ongoingFunction).Add(line2struct(line, funcs))
End If
Catch ex As textException
ex.row = index + 1
ex.overallPos = orgText.IndexOf(Lines(index))
Throw
Catch ex As Exception
Dim ex2 As New textException(ex.Message, index + 1)
ex2.overallPos = orgText.IndexOf(Lines(index))
Throw ex2
End Try
End If
Next
For i As Integer = 0 To funcs.Count - 1
Dim f As CMcfBase.SFunction = funcs(i)
f.data = funcData(i).ToArray()
funcs(i) = f
Next
iTxtLines = Lines
iFunctions = funcs.ToArray()
End Sub
Public ReadOnly Property TxtLines() As String()
Get
Return iTxtLines
End Get
End Property
Public ReadOnly Property Functions() As CMcfBase.SFunction()
Get
Return iFunctions
End Get
End Property
Private Function RemoveComments(ByVal sText As String) As String
Const sStart$ = "/*", sEnd$ = "*/", sLine = "//"
Dim bIsComment As Boolean = False
Dim bInQuotes As Boolean = False
Dim lPos%, N%
Dim lastNline As Long = 0
If Len(Trim$(sText)) = 0 Then RemoveComments = vbNullString : Exit Function
For N = 1 To Len(sText)
Select Case Mid$(sText, N, 1)
Case Chr(34) 'quote
'
If Not bIsComment AndAlso ((N > 1 AndAlso bInQuotes AndAlso sText(N - 2) <> "\") OrElse (N < 2 OrElse Not bInQuotes OrElse sText(N - 3) = "\")) Then bInQuotes = Not bInQuotes
'Case "'"
' If Not (bIsComment Or bInQuotes) Then
' Mid(sText, N) = StrDup(Len(sText) - N + 1, Chr(0))
' Exit For
' End If
Case Else
Select Case Mid$(sText, N, 2)
Case sLine
If Not (bIsComment Or bInQuotes) Then
Dim deb As Boolean = False
Dim lineend As Integer = sText.IndexOf(LineFeed, N + 1)
If lineend < 0 Then lineend = sText.Length
Mid$(sText, N, lineend - N + 1) = StrDup(lineend - N + 1, Chr(0))
N = N + 1
End If
Case sStart
If Not bInQuotes Then
lPos = N
bIsComment = True
N = N + 1
End If
Case sEnd
If Not bInQuotes Then
If lPos = 0 Then lPos = 1
Mid$(sText, lPos, N + Len(sEnd) - lPos) = StrDup(N + Len(sEnd) - lPos, Chr(0))
N = N + 1
bIsComment = False
End If
Case vbNewLine
If Not bIsComment Then
If bInQuotes Then
Dim exText As String = Mid$(sText, N - 10, 20)
Dim ex As New textException(7, 0, N - lastNline - 2)
ex.overallPos = lastNline + 1
Throw ex
End If
End If
End Select
End Select
If Mid$(sText, N, LineFeed.Length) = LineFeed Then lastNline = N
Next N
If bIsComment Then
If lPos = 0 Then lPos = 1
Mid$(sText, lPos, N + Len(sEnd) - lPos) = StrDup(N + Len(sEnd) - lPos, Chr(0))
End If
RemoveComments = Replace(sText, Chr(0), "")
If Len(Trim$(RemoveComments)) Then RemoveComments = RemoveComments & LineFeed
End Function
Private Shared Function line2struct(ByVal txt As String, ByRef funcs As List(Of CMcfBase.SFunction)) As CMcfBase.SScriptLine
Dim out As New CMcfBase.SScriptLine
If txt.IndexOf("(") < 0 OrElse txt.IndexOf(");") < 0 Then Throw New textException(1, 0, txt.Length)
Dim a As String() = {txt.Substring(0, txt.IndexOf("(")), txt.Substring(txt.IndexOf("(") + 1)}
Dim b As String() = {a(1).Substring(0, a(1).LastIndexOf(");"))}
'If b(0).Length < 1 Then Throw New textException(3, a(0).Length, 0) 'cose we have Else();
' parsing parameters
Dim qIn As Boolean = False
Dim pCh As Char = Chr(0)
Dim buffer As String = ""
Dim pars As New ArrayList
For kl As Integer = 0 To b(0).Length - 1
Dim ch As Char = b(0)(kl)
If ch = ControlChars.Quote AndAlso pCh <> "\" Then
qIn = Not qIn
buffer &= ch
Else
If Not qIn AndAlso ch = "," Then
pars.Add(buffer)
buffer = ""
Else
buffer &= ch
End If
End If
pCh = ch
Next
If buffer <> "" Then pars.Add(buffer)
Dim type As Integer = -1
For i As Integer = 0 To funcs.Count - 1
If Trim(a(0)) = funcs(i).name AndAlso funcs(i).parameterTypes.Length = pars.Count Then
type = i
End If
Next
' end parsing parameters
If type < 0 Then Throw New textException(2, 0, a(0).Length)
out.callTo = type
If pars.Count > 0 Then
Dim pS(pars.Count - 1) As CMcfBase.SParamElem
Dim pos As Integer = 0
For i As Integer = 0 To pars.Count - 1
Try
pS(i) = param2elem(Trim(pars(i)), funcs(out.callTo).parameterTypes(i))
Catch ex As FormatException
Throw New textException(6, pos + a(0).Length, pars(i).Length)
Catch ex As OverflowException
Throw New textException(5, pos + a(0).Length, pars(i).Length)
End Try
pos += pars(i).length + 1
Next
out.parameters = pS
Else
out.parameters = New CMcfBase.SParamElem() {}
End If
'If pars.Count <> out.func.parameterCount Then Throw New textException(4, a(0).Length + 1, b(0).Length)
pars = Nothing
Return out
End Function
Private Shared Function param2elem(ByVal param As String, ByVal type As CMcfBase.DataType) As CMcfBase.SParamElem
Dim out As New CMcfBase.SParamElem
out.type = type
Select Case out.type
Case CMcfBase.DataType.EBool
out.value = (param = "true")
Case CMcfBase.DataType.EFloat
out.value = Single.Parse(param, iCulture)
Case CMcfBase.DataType.EInteger
If param.Length > 2 AndAlso param.Substring(0, 2) = "0x" Then
out.value = Convert.ToUInt32(param.Substring(2), 16)
Else
out.value = UInt32.Parse(param)
End If
Case CMcfBase.DataType.EString
out.value = param.Substring(1, param.Length - 2)
End Select
Return out
End Function
Private Shared Function line2func(ByVal line As String, ByVal id As Integer) As CMcfBase.SFunction
If line.IndexOf("(") < 0 OrElse line.IndexOf(")") < 0 Then Throw New textException(1, 0, line.Length)
Dim func As New CMcfBase.SFunction
Dim a As String() = line.Split("(")
Dim c As String() = a(0).Split(" ")
For i As Integer = 0 To CMcfBase.DataTypeString.Length - 1
If c(0) = CMcfBase.DataTypeString(i) Then
func.returnType = CType(i, CMcfBase.DataType)
End If
Next
func.name = c(1)
func.isExternal = (a(1).Split(")").Length > 1 AndAlso a(1).Split(")")(1) = ";")
Dim b As String() = a(1).Split(")")(0).Split(",")
Dim pS As New List(Of CMcfBase.DataType)
If b.Length > 1 OrElse b(0).Trim() <> "" Then
For i As Integer = 0 To b.Length - 1
Dim k As Integer = Array.IndexOf(CMcfBase.DataTypeString, b(i).Trim())
If k > 0 Then
pS.Add(CType(k, CMcfBase.DataType))
Else
Throw New textException(5, 0, line.Length)
End If
Next
End If
func.parameterTypes = pS.ToArray()
func.id = id
Return func
End Function
Private Function addFormatting(ByVal line As String, ByVal func As CMcfBase.SFunction) As String
Dim Ryl2QuestFunctions As String() = {"QuestSkillPointBonus", "QuestType", "QuestArea", "QuestTitle", "QuestDesc", "QuestShortDesc", "QuestIcon", "QuestCompleteSave", "QuestLevel", "QuestAward", "AddPhase", "Phase_Target", "Trigger_Start", "Trigger_Puton", "Trigger_Geton", "Trigger_Talk", "Trigger_Kill", "Trigger_Pick", "Trigger_Fame", "Trigger_LevelTalk", "Else", "Event_Disappear", "Event_Get", "Event_Spawn", "Event_MonsterDrop", "Event_Award", "Event_MsgBox", "Event_Phase", "Event_End", "Event_AwardItem", "Event_AddQuest", "Event_Move", "Event_TheaterMode"}
If RYLFileType = CMcfBase.EFileType.EQuest Then
Dim defLvl As Integer = 3
Dim lvl0 As String() = {"QuestEnd", "QuestStart"}
Dim lvl1 As String() = {"Quest", "AddPhase"}
Dim lvl2 As String() = {"Phase_", "Trigger_", "Else"}
For Each l As String In lvl0
If func.name.StartsWith(l) Then
GoTo addEnters
End If
Next
For Each l As String In lvl1
If func.name.StartsWith(l) Then
line = vbTab & line
GoTo addEnters
End If
Next
For Each l As String In lvl2
If func.name.StartsWith(l) Then
line = vbTab & vbTab & line
GoTo addEnters
End If
Next
line = vbTab & vbTab & vbTab & line
GoTo addEnters
ElseIf RYLFileType = CMcfBase.EFileType.ENpcScript Then
If func.name = "SetNPC" Then GoTo addEnters
line = vbTab & line
GoTo addEnters
End If
'Return line
addEnters:
If func.name = "SetNPC" OrElse func.name = "QuestStart" Then
line = LineFeed & LineFeed & line
ElseIf func.name = "AddPhase" Then
line = LineFeed & line
End If
Return line
End Function
End Class
Public Class textException
Inherits Exception
Public Sub New(ByVal nr As Integer, ByVal pos As Long, ByVal len As Long, Optional ByVal line As Long = 0)
code = nr
position = pos
length = len
row = line
End Sub
Public Sub New(ByVal text As String, Optional ByVal line As Long = 0)
code = &HFF
otherInf = text
row = line
End Sub
Public code As Integer
Public position As Long
Public overallPos As Long
Public length As Long
Public row As Long
Private otherInf As String
Public Overrides Function ToString() As String
Select Case code
Case 1 : Return "Non valid line. ( or ); is missing"
Case 2 : Return "Non valid line. Unknown function or incorrect parameter count"
'Case 3 : Return "Non valid line. No function parameters"
Case 4 : Return "Non valid line. Function parameter count invalid"
Case 5 : Return "Non valid line. Function parameter out of range"
Case 6 : Return "Non valid line. Function parameter is not in HEX format"
Case 7 : Return "String parameter not ended"
Case &HFF : Return otherInf
End Select
Return "Non valid script"
End Function
End Class