123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using NTERA.Core;
- using NTERA.EmuEra.Game.EraEmu.GameData.Expression;
- using NTERA.EmuEra.Game.EraEmu.GameData.Variable;
- using NTERA.EmuEra.Game.EraEmu.Sub;
- namespace NTERA.EmuEra.Game.EraEmu.GameProc
- {
- //1756 インナークラス解除して一般に開放
- //難読化用属性。enum.ToString()やenum.Parse()を行うなら(Exclude=true)にすること。
- [Obfuscation(Exclude = false)]
- internal enum SystemStateCode
- {
- __CAN_SAVE__ = 0x10000,//セーブロード画面を呼び出し可能か?
- __CAN_BEGIN__ = 0x20000,//BEGIN命令を呼び出し可能か?
- Title_Begin = 0,//初期状態
- Openning = 1,//最初の入力待ち
- Train_Begin = 0x10,//BEGIN TRAINから。
- Train_CallEventTrain = 0x11,//@EVENTTRAINの呼び出し中。スキップ可能
- Train_CallShowStatus = 0x12,//@SHOW_STATUSの呼び出し中
- Train_CallComAbleXX = 0x13,//@COM_ABLExxの呼び出し中。スキップの場合、RETURN 1とする。
- Train_CallShowUserCom = 0x14,//@SHOW_USERCOMの呼び出し中
- Train_WaitInput = 0x15,//入力待ち状態。選択が実行可能ならEVENTCOMからCOMxx、そうでなければ@USERCOMにRESULTを渡す
- Train_CallEventCom = 0x16 | __CAN_BEGIN__,//@EVENTCOMの呼び出し中
- Train_CallComXX = 0x17 | __CAN_BEGIN__,//@COMxxの呼び出し中
- Train_CallSourceCheck = 0x18 | __CAN_BEGIN__,//@SOURCE_CHECKの呼び出し中
- Train_CallEventComEnd = 0x19 | __CAN_BEGIN__,//@EVENTCOMENDの呼び出し中。スキップ可能。Train_CallEventTrainへ帰る。@USERCOMの呼び出し中もここ
- Train_DoTrain = 0x1A,
- AfterTrain_Begin = 0x20 | __CAN_BEGIN__,//BEGIN AFTERTRAINから。@EVENTENDを呼び出してNormalへ。
- Ablup_Begin = 0x30,//BEGIN ABLUPから。
- Ablup_CallShowJuel = 0x31,//@SHOW_JUEL
- Ablup_CallShowAblupSelect = 0x32,//@SHOW_ABLUP_SELECT
- Ablup_WaitInput = 0x33,//
- Ablup_CallAblupXX = 0x34 | __CAN_BEGIN__,//@ABLUPxxがない場合は、@USERABLUPにRESULTを渡す。Ablup_CallShowJuelへ戻る。
- Turnend_Begin = 0x40 | __CAN_BEGIN__,//BEGIN TURNENDから。@EVENTTURNENDを呼び出してNormalへ。
- Shop_Begin = 0x50 | __CAN_SAVE__,//BEGIN SHOPから
- Shop_CallEventShop = 0x51 | __CAN_BEGIN__ | __CAN_SAVE__,//@EVENTSHOPの呼び出し中。スキップ可能
- Shop_CallShowShop = 0x52 | __CAN_SAVE__,//@SHOW_SHOPの呼び出し中
- Shop_WaitInput = 0x53 | __CAN_SAVE__,//入力待ち状態。アイテムが存在するならEVENTBUYにBOUGHT、そうでなければ@USERSHOPにRESULTを渡す
- Shop_CallEventBuy = 0x54 | __CAN_BEGIN__ | __CAN_SAVE__,//@USERSHOPまた@EVENTBUYはの呼び出し中
- SaveGame_Begin = 0x100,//SAVEGAMEから
- SaveGame_WaitInput = 0x101,//入力待ち
- SaveGame_WaitInputOverwrite = 0x102,//上書きの許可待ち
- SaveGame_CallSaveInfo = 0x103,//@SAVEINFO呼び出し中。20回。
- LoadGame_Begin = 0x110,//LOADGAMEから
- LoadGame_WaitInput = 0x111,//入力待ち
- LoadGameOpenning_Begin = 0x120,//最初に[1]を選択したとき。
- LoadGameOpenning_WaitInput = 0x121,//入力待ち
- //AutoSave_Begin = 0x200,
- AutoSave_CallSaveInfo = 0x201,
- AutoSave_CallUniqueAutosave = 0x202,
- AutoSave_Skipped = 0x203,
- LoadData_DataLoaded = 0x210,//データロード直後
- LoadData_CallSystemLoad = 0x211 | __CAN_BEGIN__,//データロード直後
- LoadData_CallEventLoad = 0x212 | __CAN_BEGIN__,//@EVENTLOADの呼び出し中。スキップ可能
- Openning_TitleLoadgame = 0x220,
- System_Reloaderb = 0x230,
- First_Begin = 0x240,
- Normal = 0xFFFF | __CAN_BEGIN__ | __CAN_SAVE__//特に何でもないとき。ScriptEndに達したらエラー
- }
- //難読化用属性。enum.ToString()やenum.Parse()を行うなら(Exclude=true)にすること。
- [Obfuscation(Exclude = false)]
- internal enum BeginType
- {
- NULL = 0,
- SHOP = 2,
- TRAIN = 3,
- AFTERTRAIN = 4,
- ABLUP = 5,
- TURNEND = 6,
- FIRST = 7,
- TITLE = 8
- }
- internal sealed class ProcessState
- {
- public ProcessState(IConsole console)
- {
- if (Program.DebugMode)//DebugModeでなければ知らなくて良い
- this.console = console;
- }
- readonly IConsole console;
- readonly List<CalledFunction> functionList = new List<CalledFunction>();
- private LogicalLine currentLine;
- //private LogicalLine nextLine;
- public int lineCount;
- public int currentMin = 0;
- //private bool sequential;
- public bool ScriptEnd => functionList.Count == currentMin;
- public int functionCount => functionList.Count;
- SystemStateCode sysStateCode = SystemStateCode.Title_Begin;
- BeginType begintype = BeginType.NULL;
- public bool isBegun => (begintype != BeginType.NULL) ? true : false;
- public LogicalLine CurrentLine { get => currentLine;
- set { currentLine = value; } }
- public LogicalLine ErrorLine => currentLine;
- //IF文中でELSEIF文の中身をチェックするなどCurrentLineと作業中のLineが違う時にセットする
- //public LogicalLine RunningLine { get; set; }
- //1755a 呼び出し元消滅
- //public bool Sequential { get { return sequential; } }
- public CalledFunction CurrentCalled => functionList[functionList.Count - 1];
- public SystemStateCode SystemState
- {
- get => sysStateCode;
- set { sysStateCode = value; }
- }
- public void ShiftNextLine()
- {
- currentLine = currentLine.NextLine;
- //nextLine = nextLine.NextLine;
- //RunningLine = null;
- //sequential = true;
- //GlobalStatic.Process.lineCount++;
- lineCount++;
- }
- /// <summary>
- /// 関数内の移動。JUMPではなくGOTOやIF文など
- /// </summary>
- /// <param name="line"></param>
- public void JumpTo(LogicalLine line)
- {
- currentLine = line;
- lineCount++;
- //sequential = false;
- //ShfitNextLine();
- }
- public void SetBegin(string keyword)
- {//TrimとToUpper済みのはず
- switch (keyword)
- {
- case "SHOP":
- SetBegin(BeginType.SHOP); return;
- case "TRAIN":
- SetBegin(BeginType.TRAIN); return;
- case "AFTERTRAIN":
- SetBegin(BeginType.AFTERTRAIN); return;
- case "ABLUP":
- SetBegin(BeginType.ABLUP); return;
- case "TURNEND":
- SetBegin(BeginType.TURNEND); return;
- case "FIRST":
- SetBegin(BeginType.FIRST); return;
- case "TITLE":
- SetBegin(BeginType.TITLE); return;
- }
- throw new CodeEE("BEGINのキーワード\"" + keyword + "\"は未定義です");
- }
- public void SetBegin(BeginType type)
- {
- string errmes = "";
- switch (type)
- {
- case BeginType.SHOP:
- case BeginType.TRAIN:
- case BeginType.AFTERTRAIN:
- case BeginType.ABLUP:
- case BeginType.TURNEND:
- case BeginType.FIRST:
- if ((sysStateCode & SystemStateCode.__CAN_BEGIN__) != SystemStateCode.__CAN_BEGIN__)
- {
- errmes = "BEGIN";
- goto err;
- }
- break;
- //1.729 BEGIN TITLEはどこでも使えるように
- case BeginType.TITLE:
- break;
- //BEGINの処理中でチェック済み
- //default:
- // throw new ExeEE("不適当なBEGIN呼び出し");
- }
- begintype = type;
- return;
- err:
- CalledFunction func = functionList[0];
- string funcName = func.FunctionName;
- throw new CodeEE("@" + funcName + "中で" + errmes + "命令を実行することはできません");
- }
- public void SaveLoadData(bool saveData)
- {
- if (saveData)
- sysStateCode = SystemStateCode.SaveGame_Begin;
- else
- sysStateCode = SystemStateCode.LoadGame_Begin;
- //ClearFunctionList();
- }
- public void ClearFunctionList()
- {
- if (Program.DebugMode && !isClone && GlobalStatic.Process.MethodStack() == 0)
- console.DebugClearTraceLog();
- foreach (CalledFunction called in functionList)
- if (called.CurrentLabel.hasPrivDynamicVar)
- called.CurrentLabel.Out();
- functionList.Clear();
- begintype = BeginType.NULL;
- }
- public bool calledWhenNormal = true;
- /// <summary>
- /// BEGIN命令によるプログラム状態の変化
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- public void Begin()
- {
- //@EVENTSHOPからの呼び出しは一旦破棄
- if (sysStateCode == SystemStateCode.Shop_CallEventShop)
- return;
- switch (begintype)
- {
- case BeginType.SHOP:
- if (sysStateCode == SystemStateCode.Normal)
- calledWhenNormal = true;
- else
- calledWhenNormal = false;
- sysStateCode = SystemStateCode.Shop_Begin;
- break;
- case BeginType.TRAIN:
- sysStateCode = SystemStateCode.Train_Begin;
- break;
- case BeginType.AFTERTRAIN:
- sysStateCode = SystemStateCode.AfterTrain_Begin;
- break;
- case BeginType.ABLUP:
- sysStateCode = SystemStateCode.Ablup_Begin;
- break;
- case BeginType.TURNEND:
- sysStateCode = SystemStateCode.Turnend_Begin;
- break;
- case BeginType.FIRST:
- sysStateCode = SystemStateCode.First_Begin;
- break;
- case BeginType.TITLE:
- sysStateCode = SystemStateCode.Title_Begin;
- break;
- //セット時に判定してるので、ここには来ないはず
- //default:
- // throw new ExeEE("不適当なBEGIN呼び出し");
- }
- if (Program.DebugMode)
- {
- console.DebugClearTraceLog();
- console.DebugAddTraceLog("BEGIN:" + begintype);
- }
- foreach (CalledFunction called in functionList)
- if (called.CurrentLabel.hasPrivDynamicVar)
- called.CurrentLabel.Out();
- functionList.Clear();
- begintype = BeginType.NULL;
- }
- /// <summary>
- /// システムによる強制的なBEGIN
- /// </summary>
- /// <param name="type"></param>
- public void Begin(BeginType type)
- {
- begintype = type;
- sysStateCode = SystemStateCode.Title_Begin;
- Begin();
- }
- public LogicalLine GetCurrentReturnAddress
- {
- get
- {
- if (functionList.Count == currentMin)
- return null;
- return functionList[functionList.Count - 1].ReturnAddress;
- }
- }
- public LogicalLine GetReturnAddressSequensial(int curerntDepth)
- {
- if (functionList.Count == currentMin)
- return null;
- return functionList[functionList.Count - curerntDepth - 1].ReturnAddress;
- }
- public string Scope
- {
- get
- {
- //スクリプトの実行中処理からしか呼び出されないので、ここはない…はず
- //if (functionList.Count == 0)
- //{
- // throw new ExeEE("実行中の関数が存在しません");
- //}
- if (functionList.Count == 0)
- return null;//1756 デバッグコマンドから呼び出されるようになったので
- return functionList[functionList.Count - 1].FunctionName;
- }
- }
- public void Return(Int64 ret)
- {
- if (IsFunctionMethod)
- {
- ReturnF(null);
- return;
- }
- //sequential = false;//いずれにしろ順列ではない。
- //呼び出し元は全部スクリプト処理
- //if (functionList.Count == 0)
- //{
- // throw new ExeEE("実行中の関数が存在しません");
- //}
- CalledFunction called = functionList[functionList.Count - 1];
- if (called.IsJump)
- {//JUMPした場合。即座にRETURN RESULTする。
- if (called.TopLabel.hasPrivDynamicVar)
- called.TopLabel.Out();
- functionList.Remove(called);
- if (Program.DebugMode)
- console.DebugRemoveTraceLog();
- Return(ret);
- return;
- }
- if (!called.IsEvent)
- {
- if (called.TopLabel.hasPrivDynamicVar)
- called.TopLabel.Out();
- currentLine = null;
- }
- else
- {
- if (called.CurrentLabel.hasPrivDynamicVar)
- called.CurrentLabel.Out();
- //#Singleフラグ付き関数で1が返された。
- //1752 非0ではなく1と等価であることを見るように修正
- //1756 全てを終了ではなく#PRIや#LATERのグループごとに修正
- if (called.IsOnly)
- called.FinishEvent();
- else if ((called.HasSingleFlag) && (ret == 1))
- called.ShiftNextGroup();
- else
- called.ShiftNext();//次の同名関数に進む。
- currentLine = called.CurrentLabel;//関数の始点(@~~)へ移動。呼ぶべき関数が無ければnull
- if (called.CurrentLabel != null)
- {
- lineCount++;
- if (called.CurrentLabel.hasPrivDynamicVar)
- called.CurrentLabel.In();
- }
- }
- if (Program.DebugMode)
- console.DebugRemoveTraceLog();
- //関数終了
- if (currentLine == null)
- {
- currentLine = called.ReturnAddress;
- functionList.RemoveAt(functionList.Count - 1);
- if (currentLine == null)
- {
- //この時点でfunctionListは空のはず
- //functionList.Clear();//全て終了。stateEndProcessに処理を返す
- if (begintype != BeginType.NULL)//BEGIN XXが行なわれていれば
- {
- Begin();
- }
- return;
- }
- lineCount++;
- //ShfitNextLine();
- return;
- }
- if (Program.DebugMode)
- {
- FunctionLabelLine label = called.CurrentLabel;
- console.DebugAddTraceLog("CALL :@" + label.LabelName + ":" + label.Position + "行目");
- }
- lineCount++;
- //ShfitNextLine();
- }
- public void IntoFunction(CalledFunction call, UserDefinedFunctionArgument srcArgs, ExpressionMediator exm)
- {
- if (call.IsEvent)
- {
- foreach (CalledFunction called in functionList)
- {
- if (called.IsEvent)
- throw new CodeEE("EVENT関数の解決前にCALLEVENT命令が行われました");
- }
- }
- if (Program.DebugMode)
- {
- FunctionLabelLine label = call.CurrentLabel;
- if (call.IsJump)
- console.DebugAddTraceLog("JUMP :@" + label.LabelName + ":" + label.Position + "行目");
- else
- console.DebugAddTraceLog("CALL :@" + label.LabelName + ":" + label.Position + "行目");
- }
- if (srcArgs != null)
- {
- //引数の値を確定させる
- srcArgs.SetTransporter(exm);
- //プライベート変数更新
- if (call.TopLabel.hasPrivDynamicVar)
- call.TopLabel.In();
- //更新した変数へ引数を代入
- for (int i = 0; i < call.TopLabel.Arg.Length; i++)
- {
- if (srcArgs.Arguments[i] != null)
- {
- if (call.TopLabel.Arg[i].Identifier.IsReference)
- ((ReferenceToken)(call.TopLabel.Arg[i].Identifier)).SetRef(srcArgs.TransporterRef[i]);
- else if (srcArgs.Arguments[i].GetOperandType() == typeof(Int64))
- call.TopLabel.Arg[i].SetValue(srcArgs.TransporterInt[i], exm);
- else
- call.TopLabel.Arg[i].SetValue(srcArgs.TransporterStr[i], exm);
- }
- }
- }
- else//こっちに来るのはシステムからの呼び出し=引数は存在しない関数のみ ifネストの外に出していい気もしないでもないがはてさて
- {
- //プライベート変数更新
- if (call.TopLabel.hasPrivDynamicVar)
- call.TopLabel.In();
- }
- functionList.Add(call);
- //sequential = false;
- currentLine = call.CurrentLabel;
- lineCount++;
- //ShfitNextLine();
- }
- #region userdifinedmethod
- public bool IsFunctionMethod => functionList[currentMin].TopLabel.IsMethod;
- public SingleTerm MethodReturnValue;
- public void ReturnF(SingleTerm ret)
- {
- //読み込み時のチェック済みのはず
- //if (!IsFunctionMethod)
- // throw new ExeEE("ReturnFと#FUNCTIONのチェックがおかしい");
- //sequential = false;//いずれにしろ順列ではない。
- //呼び出し元はRETURNFコマンドか関数終了時のみ
- //if (functionList.Count == 0)
- // throw new ExeEE("実行中の関数が存在しません");
- //非イベント呼び出しなので、これは起こりえない
- //else if (functionList.Count != 1)
- // throw new ExeEE("関数が複数ある");
- if (Program.DebugMode)
- {
- console.DebugRemoveTraceLog();
- }
- //OutはGetValue側で行う
- //functionList[0].TopLabel.Out();
- currentLine = functionList[functionList.Count - 1].ReturnAddress;
- functionList.RemoveAt(functionList.Count - 1);
- //nextLine = null;
- MethodReturnValue = ret;
- }
- #endregion
- bool isClone;
- public bool IsClone { get => isClone;
- set { isClone = value; } }
- // functionListのコピーを必要とする呼び出し元が無かったのでコピーしないことにする。
- public ProcessState Clone()
- {
- ProcessState ret = new ProcessState(console);
- ret.isClone = true;
- //どうせ消すからコピー不要
- //foreach (CalledFunction func in functionList)
- // ret.functionList.Add(func.Clone());
- ret.currentLine = currentLine;
- //ret.nextLine = this.nextLine;
- //ret.sequential = this.sequential;
- ret.sysStateCode = sysStateCode;
- ret.begintype = begintype;
- //ret.MethodReturnValue = this.MethodReturnValue;
- return ret;
- }
- //public ProcessState CloneForFunctionMethod()
- //{
- // ProcessState ret = new ProcessState(console);
- // ret.isClone = true;
- // //どうせ消すからコピー不要
- // //foreach (CalledFunction func in functionList)
- // // ret.functionList.Add(func.Clone());
- // ret.currentLine = this.currentLine;
- // ret.nextLine = this.nextLine;
- // //ret.sequential = this.sequential;
- // ret.sysStateCode = this.sysStateCode;
- // ret.begintype = this.begintype;
- // //ret.MethodReturnValue = this.MethodReturnValue;
- // return ret;
- //}
- }
- }
|