コード例 #1
0
ファイル: VMThread.cs プロジェクト: LinSianTing/FreeSO
        public VMPrimitiveExitCode ExecuteSubRoutine(VMStackFrame frame, ushort opcode, VMSubRoutineOperand operand)
        {
            VMRoutine bhav = null;

            GameObject CodeOwner;

            if (opcode >= 8192)
            {
                // Semi-Global sub-routine call
                bhav = (VMRoutine)frame.ScopeResource.SemiGlobal.GetRoutine(opcode);
            }
            else if (opcode >= 4096)
            {
                // Private sub-routine call
                bhav = (VMRoutine)frame.ScopeResource.GetRoutine(opcode);
            }
            else
            {
                // Global sub-routine call
                //CodeOwner = frame.Global.Resource;
                bhav = (VMRoutine)frame.Global.Resource.GetRoutine(opcode);
            }

            CodeOwner = frame.CodeOwner;

            ExecuteSubRoutine(frame, bhav, CodeOwner, operand);
#if IDE_COMPAT
            if (Stack.LastOrDefault().GetCurrentInstruction().Breakpoint || ThreadBreak == VMThreadBreakMode.StepIn)
            {
                Breakpoint(frame, "Stepped in.");
                ContinueExecution = false;
            }
            else
#endif
            {
                ContinueExecution = true;
            }

            return(VMPrimitiveExitCode.CONTINUE);
        }
コード例 #2
0
ファイル: VMQueuedAction.cs プロジェクト: jwofles/ForkSO
        public ushort ResultCheckCounter = 0;  //how many times the interaction result has been checked. used for timeout.

        public VMStackFrame ToStackFrame(VMEntity caller)
        {
            var frame = new VMStackFrame
            {
                Caller      = caller,
                Callee      = Callee,
                CodeOwner   = CodeOwner,
                Routine     = ActionRoutine,
                StackObject = StackObject,
                ActionTree  = true
            };

            if (Args == null)
            {
                frame.Args = new short[4];               //always 4? i got crashes when i used the value provided by the routine, when for that same routine edith displayed 4 in the properties...
            }
            else
            {
                frame.Args = Args;  //WARNING - if you use this, the args array MUST have the same number of elements the routine is expecting!
            }
            return(frame);
        }
コード例 #3
0
        private void MoveToInstruction(VMStackFrame frame, byte instruction, bool continueExecution)
        {
            if (frame is VMRoutingFrame)
            {
                //TODO: Handle returning false into the pathfinder (indicates failure)
                return;
            }

            switch (instruction)
            {
            case 255:
                Pop(VMPrimitiveExitCode.RETURN_FALSE);
                break;

            case 254:
                Pop(VMPrimitiveExitCode.RETURN_TRUE); break;

            case 253:
                Pop(VMPrimitiveExitCode.ERROR); break;

            default:
                frame.InstructionPointer = instruction;
                if (frame.GetCurrentInstruction().Breakpoint ||
                    (ThreadBreak != VMThreadBreakMode.Active && (
                         ThreadBreak == VMThreadBreakMode.StepIn ||
                         (ThreadBreak == VMThreadBreakMode.StepOver && Stack.Count - 1 <= BreakFrame) ||
                         (ThreadBreak == VMThreadBreakMode.StepOut && Stack.Count <= BreakFrame)
                         )))
                {
                    Breakpoint(frame);
                }
                break;
            }

            ContinueExecution = (ThreadBreak != VMThreadBreakMode.Pause) && continueExecution;
        }
コード例 #4
0
        public static object GetSuit(VMStackFrame context, VMSuitScope scope, ushort id)
        {
            STR suitTable = null;

            var avatar = (VMAvatar)context.Caller;

            switch (scope)
            {
            case VMSuitScope.Object:
                suitTable = context.CodeOwner.Resource.Get <STR>(304);
                break;

            case VMSuitScope.Global:
                suitTable = context.Global.Resource.Get <STR>(304);
                break;

            case VMSuitScope.Person:
                //get outfit from person
                if (context.VM.TS1)
                {
                    return(GetPersonSuitTS1((VMAvatar)context.Caller, id));
                }

                var  type = (VMPersonSuits)id;
                bool male = (avatar.GetPersonData(VMPersonDataVariable.Gender) == 0);
                switch (type)
                {
                //todo: (tail etc), cockroach head

                case VMPersonSuits.DefaultDaywear:
                    return(avatar.DefaultSuits.Daywear.ID);

                case VMPersonSuits.Naked:
                    return((ulong)(male ? 0x24E0000000D : 0x10000000D));

                case VMPersonSuits.DefaultSwimwear:
                    return(avatar.DefaultSuits.Swimwear.ID);

                case VMPersonSuits.JobOutfit:
                    if (context.VM.TS1)
                    {
                        return(null);
                    }
                    var job = avatar.GetPersonData(VMPersonDataVariable.OnlineJobID);
                    if (job < 1 || job > 5)
                    {
                        return(null);
                    }
                    var level = Math.Max(0, Math.Min(3, (avatar.GetPersonData(VMPersonDataVariable.OnlineJobGrade) - 1) / 4));
                    return((ulong)(JobOutfits[male?0:1][job - 1][level]));

                case VMPersonSuits.DefaultSleepwear:
                    return(avatar.DefaultSuits.Sleepwear.ID);

                case VMPersonSuits.SkeletonPlus:
                    return((ulong)(0x5750000000D));

                case VMPersonSuits.SkeletonMinus:
                    return((ulong)(0x5740000000D));

                case VMPersonSuits.TeleporterMishap:
                    return((ulong)(male ? 0x2900000000D : 0x4A0000000D));


                case VMPersonSuits.DynamicDaywear:
                    return(avatar.DynamicSuits.Daywear);

                case VMPersonSuits.DynamicSleepwear:
                    return(avatar.DynamicSuits.Sleepwear);

                case VMPersonSuits.DynamicSwimwear:
                    return(avatar.DynamicSuits.Swimwear);

                case VMPersonSuits.DynamicCostume:
                    return(avatar.DynamicSuits.Costume);

                case VMPersonSuits.DecorationHead:
                    return(avatar.Decoration.Head);

                case VMPersonSuits.DecorationBack:
                    return(avatar.Decoration.Back);

                case VMPersonSuits.DecorationShoes:
                    return(avatar.Decoration.Shoes);

                case VMPersonSuits.DecorationTail:
                    return(avatar.Decoration.Tail);
                }

                return(null);
            }

            if (suitTable != null)
            {
                var suitFile = suitTable.GetString(id) + ".apr";

                return(suitFile);
                //var apr = FSO.Content.Content.Get().AvatarAppearances.Get(suitFile);
                //return apr;
            }
            return(null);
        }
コード例 #5
0
ファイル: VMDialogHandler.cs プロジェクト: LinSianTing/FreeSO
        public static string ParseDialogString(VMStackFrame context, string input, STR source, int depth)
        {
            if (depth > 10)
            {
                return(input);
            }
            int           state   = 0;
            StringBuilder command = new StringBuilder();
            StringBuilder output  = new StringBuilder();

            if (input == null)
            {
                return("Missing String!!!");
            }

            for (int i = 0; i < input.Length; i++)
            {
                if (state == 0)
                {
                    if (input[i] == '$')
                    {
                        state = 1; //start parsing string
                        command.Clear();
                    }
                    else
                    {
                        output.Append(input[i]);
                    }
                }
                else
                {
                    command.Append(input[i]);
                    if (i == input.Length - 1 || !CommandSubstrValid(command.ToString()))
                    {
                        if (i != input.Length - 1 || char.IsDigit(input[i]))
                        {
                            command.Remove(command.Length - 1, 1);
                            i--;
                        }

                        var     cmdString = command.ToString();
                        short[] values    = new short[3];
                        if (cmdString.Length > 1 && cmdString[cmdString.Length - 1] == ':')
                        {
                            try
                            {
                                if (cmdString == "DynamicStringLocal:" || cmdString == "TimeLocal:" || cmdString == "JobOffer:" || cmdString == "Job:" || cmdString == "JobDesc:" || cmdString == "DateLocal:")
                                {
                                    values[1] = -1;
                                    values[2] = -1;
                                    for (int j = 0; j < 3; j++)
                                    {
                                        char   next = input[++i];
                                        string num  = "";
                                        while (char.IsDigit(next))
                                        {
                                            num += next;
                                            next = (++i == input.Length) ? '!': input[i];
                                        }
                                        if (num == "")
                                        {
                                            values[j] = -1;
                                            if (j == 1)
                                            {
                                                values[2] = -1;
                                            }
                                            break;
                                        }
                                        values[j] = short.Parse(num);
                                        if (i == input.Length || next != ':')
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    char   next = input[++i];
                                    string num  = "";
                                    while (char.IsDigit(next))
                                    {
                                        num += next;
                                        next = (++i == input.Length) ? '!' : input[i];
                                    }
                                    values[0] = short.Parse(num);
                                }
                                i--;
                            }
                            catch (FormatException)
                            {
                            }
                        }
                        try
                        {
                            switch (cmdString)
                            {
                            case "Object":
                            case "DynamicObjectName":
                                //hack: if stack object doesn't exist and should contain owner's id,
                                //try output the callee's owner id instead for tip jar.
                                //special id for this is -1.
                                if (context.StackObjectID == -1 && !context.VM.TS1)
                                {
                                    //StackObjectOwnerID call sets the id to -1 if no owner found. (null is usually 0)
                                    output.Append(context.VM.TSOState.Names.GetNameForID(
                                                      context.VM,
                                                      (context.Callee.TSOState as VMTSOObjectState)?.OwnerID ?? 0
                                                      ));
                                }
                                else
                                {
                                    output.Append(context.StackObject.ToString());
                                }
                                break;

                            case "Me":
                                output.Append(context.Caller.ToString()); break;

                            case "TempXL:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.TempXL, values[0]).ToString()); break;

                            case "MoneyXL:":
                                output.Append("$" + VMMemory.GetBigVariable(context, Scopes.VMVariableScope.TempXL, values[0]).ToString("##,#0")); break;

                            case "Temp:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Temps, values[0]).ToString()); break;

                            case "$":
                                output.Append("$"); i--; break;

                            case "Attribute:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.MyObjectAttributes, values[0]).ToString()); break;

                            case "DynamicStringLocal:":
                                STR res = null;
                                if (values[2] != -1 && values[1] != -1)
                                {
                                    VMEntity obj = context.VM.GetObjectById((short)context.Locals[values[2]]);
                                    if (obj == null)
                                    {
                                        break;
                                    }
                                    ushort tableID = (ushort)context.Locals[values[1]];

                                    {    //local
                                        if (obj.SemiGlobal != null)
                                        {
                                            res = obj.SemiGlobal.Get <STR>(tableID);
                                        }
                                        if (res == null)
                                        {
                                            res = obj.Object.Resource.Get <STR>(tableID);
                                        }
                                        if (res == null)
                                        {
                                            res = context.Global.Resource.Get <STR>(tableID);
                                        }
                                    }
                                }
                                else if (values[1] != -1)
                                {
                                    //global table
                                    ushort tableID = (ushort)context.Locals[values[1]];
                                    res = context.Global.Resource.Get <STR>(tableID);
                                }
                                else
                                {
                                    res = source;
                                }

                                ushort index = (ushort)context.Locals[values[0]];
                                if (res != null)
                                {
                                    var str = res.GetString(index);
                                    output.Append(ParseDialogString(context, str, res, depth++));     // recursive command parsing!
                                    // this is needed for the crafting table.
                                    // though it is also, completely insane?
                                }
                                break;

                            case "Local:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]).ToString()); break;

                            case "FixedLocal:":
                                output.Append((VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]) / 100f).ToString("F2")); break;

                            case "TimeLocal:":
                                var hours  = VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]);
                                var mins   = (values[1] == -1)?0:VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[1]);
                                var suffix = (hours > 11) ? "pm" : "am";
                                if (hours > 12)
                                {
                                    hours -= 12;
                                }
                                output.Append(hours.ToString());
                                output.Append(":");
                                output.Append(mins.ToString().PadLeft(2, '0'));
                                output.Append(suffix);
                                break;

                            case "JobOffer:":
                                output.Append(Content.Content.Get().Jobs.JobOffer(
                                                  (short)VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]),
                                                  VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[1])));
                                break;

                            case "Job:":
                            case "JobDesc:":
                                var level  = VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[1]);
                                var jobStr = Content.Content.Get().Jobs.JobStrings(
                                    (short)VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]));
                                if (jobStr != null)
                                {
                                    output.Append(jobStr.GetString(level * 3 + ((cmdString == "JobDesc:")?3:4)));
                                }
                                break;

                            case "Param:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Parameters, values[0]).ToString()); break;

                            case "NameLocal:":
                                output.Append(context.VM.GetObjectById(VMMemory.GetVariable(context, Scopes.VMVariableScope.Local, values[0])).ToString()); break;

                            case "Neighbor":
                                //neighbour in stack object id
                                if (!context.VM.TS1)
                                {
                                    break;
                                }
                                var guid = Content.Content.Get().Neighborhood.GetNeighborByID(context.StackObjectID)?.GUID ?? 0;
                                var gobj = Content.Content.Get().WorldObjects.Get(guid);
                                if (gobj == null)
                                {
                                    output.Append("Unknown");
                                }
                                else
                                {
                                    output.Append(gobj.Resource.Get <FSO.Files.Formats.IFF.Chunks.CTSS>(gobj.OBJ.CatalogStringsID)?.GetString(0) ?? "Unknown");
                                }
                                break;

                            case "ListObject":
                                output.Append(new string(context.StackObject.MyList.Select(x => (char)x).ToArray()));
                                break;

                            case "CatalogLocal:":
                                var catObj = context.VM.GetObjectById(VMMemory.GetVariable(context, Scopes.VMVariableScope.Local, values[0]));
                                var cat    = catObj.Object.Resource.Get <CTSS>(catObj.Object.OBJ.CatalogStringsID)?.GetString(1);
                                output.Append(cat ?? "");
                                break;

                            case "DateLocal:":
                                var date = new DateTime(context.Locals[values[2]], context.Locals[values[1]], context.Locals[values[0]]);
                                output.Append(date.ToLongDateString());
                                break;

                            case "\\n":
                                output.Append("\n");
                                break;

                            default:
                                output.Append(cmdString);
                                break;
                            }
                        } catch (Exception)
                        {
                            //something went wrong. just skip command
                        }
                        state = 0;
                    }
                }
            }
            output.Replace("\r\n", "\r\n\r\n");
            return(output.ToString());
        }
コード例 #6
0
ファイル: VMDialogHandler.cs プロジェクト: LinSianTing/FreeSO
 public static string ParseDialogString(VMStackFrame context, string input, STR source)
 {
     return(ParseDialogString(context, input, source, 0));
 }
コード例 #7
0
        public static VMPrimitiveExitCode EvaluateCheck(VMContext context, VMEntity entity, VMStackFrame initFrame, VMQueuedAction action, List <VMPieMenuInteraction> actionStrings)
        {
            var temp       = new VMThread(context, entity, 5);
            var forceClone = !context.VM.Scheduler.RunningNow;

            //temps should only persist on check trees running within the vm tick to avoid desyncs.
            if (entity.Thread != null)
            {
                temp.TempRegisters = forceClone?(short[])entity.Thread.TempRegisters.Clone() : entity.Thread.TempRegisters;
                temp.TempXL        = forceClone ? (int[])entity.Thread.TempXL.Clone() : entity.Thread.TempXL;
            }
            temp.IsCheck       = true;
            temp.ActionStrings = actionStrings; //generate and place action strings in here
            temp.Push(initFrame);
            if (action != null)
            {
                temp.Queue.Add(action);                              //this check runs an action. We may need its interaction number, etc.
            }
            while (temp.Stack.Count > 0 && temp.DialogCooldown == 0) //keep going till we're done! idling is for losers!
            {
                temp.Tick();
                temp.ThreadBreak = VMThreadBreakMode.Active; //cannot breakpoint in check trees
            }
            if (context.VM.Aborting)
            {
                return(VMPrimitiveExitCode.ERROR);
            }
            return((temp.DialogCooldown > 0) ? VMPrimitiveExitCode.RETURN_FALSE : temp.LastStackExitCode);
        }
コード例 #8
0
 public static VMPrimitiveExitCode EvaluateCheck(VMContext context, VMEntity entity, VMStackFrame initFrame, VMQueuedAction action)
 {
     return(EvaluateCheck(context, entity, initFrame, action, null));
 }
コード例 #9
0
        private void HandleResult(VMStackFrame frame, VMInstruction instruction, VMPrimitiveExitCode result)
        {
            switch (result)
            {
            // Don't advance the instruction pointer, this primitive isnt finished yet
            case VMPrimitiveExitCode.CONTINUE_NEXT_TICK:
                ScheduleIdleStart = Context.VM.Scheduler.CurrentTickID;
                Context.VM.Scheduler.ScheduleTickIn(Entity, 1);
                ContinueExecution = false;
                break;

            case VMPrimitiveExitCode.CONTINUE_FUTURE_TICK:
                ContinueExecution = false;
                break;

            case VMPrimitiveExitCode.ERROR:
                ContinueExecution = false;
                Pop(result);
                break;

            case VMPrimitiveExitCode.RETURN_TRUE:
            case VMPrimitiveExitCode.RETURN_FALSE:
                /** pop stack and return false **/
                Pop(result);
                break;

            case VMPrimitiveExitCode.GOTO_TRUE:
                MoveToInstruction(frame, instruction.TruePointer, true);
                break;

            case VMPrimitiveExitCode.GOTO_FALSE:
                MoveToInstruction(frame, instruction.FalsePointer, true);
                break;

            case VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK:
                MoveToInstruction(frame, instruction.TruePointer, false);
                ScheduleIdleStart = Context.VM.Scheduler.CurrentTickID;
                Context.VM.Scheduler.ScheduleTickIn(Entity, 1);
                ContinueExecution = false;
                break;

            case VMPrimitiveExitCode.GOTO_FALSE_NEXT_TICK:
                MoveToInstruction(frame, instruction.FalsePointer, false);
                ScheduleIdleStart = Context.VM.Scheduler.CurrentTickID;
                Context.VM.Scheduler.ScheduleTickIn(Entity, 1);
                ContinueExecution = false;
                break;

            case VMPrimitiveExitCode.CONTINUE:
                ContinueExecution = true;
                break;

            case VMPrimitiveExitCode.INTERRUPT:
                Stack.Clear();
                QueueDirty = true;
                if (Queue.Count > 0)
                {
                    Queue.RemoveAt(0);
                }
                LastStackExitCode = result;
                break;
            }
        }
コード例 #10
0
        public bool RunInMyStack(BHAV bhav, GameObject CodeOwner, short[] passVars, VMEntity stackObj)
        {
            //a little bit hacky. We may not need to do as serious a context switch as this.
            var OldStack      = Stack;
            var OldQueue      = Queue;
            var OldCheck      = IsCheck;
            var OldQueueBlock = ActiveQueueBlock;

            VMStackFrame prevFrame = new VMStackFrame()
            {
                Caller = Entity, Callee = Entity
            };

            if (Stack.Count > 0)
            {
                prevFrame = Stack[Stack.Count - 1];
                Stack     = new List <VMStackFrame>()
                {
                    prevFrame
                };
            }
            else
            {
                Stack = new List <VMStackFrame>();
            }

            Queue = new List <VMQueuedAction>();
            if (Queue.Count > 0)
            {
                Queue.Add(Queue[0]);
            }
            IsCheck = true;

            ExecuteSubRoutine(prevFrame, bhav, CodeOwner, new VMSubRoutineOperand(passVars));
            Stack.RemoveAt(0);
            if (Stack.Count == 0)
            {
                Stack = OldStack;
                Queue = OldQueue;
                return(false);
                //bhav was invalid/empty
            }
            var frame = Stack[Stack.Count - 1];

            frame.StackObject = stackObj;

            try
            {
                while (Stack.Count > 0)
                {
                    NextInstruction();
                }
            }
            catch (Exception e)
            {
                if (e is ThreadAbortException)
                {
                    throw e;
                }
                //we need to catch these so that the parent can be restored.
            }

            //copy child stack things to parent stack
            Stack            = OldStack;
            Queue            = OldQueue;
            IsCheck          = OldCheck;
            ActiveQueueBlock = OldQueueBlock;

            return((LastStackExitCode == VMPrimitiveExitCode.RETURN_TRUE) ? true : false);
        }
コード例 #11
0
        public static VMPrimitiveExitCode EvaluateCheck(VMContext context, VMEntity entity, VMStackFrame initFrame, VMQueuedAction action, List <VMPieMenuInteraction> actionStrings)
        {
            var temp = new VMThread(context, entity, 5);

            if (entity.Thread != null)
            {
                temp.TempRegisters = entity.Thread.TempRegisters;
                temp.TempXL        = entity.Thread.TempXL;
            }
            temp.IsCheck       = true;
            temp.ActionStrings = actionStrings; //generate and place action strings in here
            temp.Push(initFrame);
            if (action != null)
            {
                temp.Queue.Add(action);                              //this check runs an action. We may need its interaction number, etc.
            }
            while (temp.Stack.Count > 0 && temp.DialogCooldown == 0) //keep going till we're done! idling is for losers!
            {
                temp.Tick();
                temp.ThreadBreak = VMThreadBreakMode.Active; //cannot breakpoint in check trees
            }
            return((temp.DialogCooldown > 0) ? VMPrimitiveExitCode.ERROR:temp.LastStackExitCode);
        }
コード例 #12
0
        private void ExecuteInstruction(VMStackFrame frame)
        {
            var instruction = frame.GetCurrentInstruction();
            var opcode      = instruction.Opcode;

            if (opcode >= 256)
            {
                BHAV bhav = null;

                GameObject CodeOwner;
                if (opcode >= 8192)
                {
                    // Semi-Global sub-routine call
                    bhav = frame.ScopeResource.SemiGlobal.Get <BHAV>(opcode);
                }
                else if (opcode >= 4096)
                {
                    // Private sub-routine call
                    bhav = frame.ScopeResource.Get <BHAV>(opcode);
                }
                else
                {
                    // Global sub-routine call
                    //CodeOwner = frame.Global.Resource;
                    bhav = frame.Global.Resource.Get <BHAV>(opcode);
                }

                CodeOwner = frame.CodeOwner;

                var operand = (VMSubRoutineOperand)instruction.Operand;
                ExecuteSubRoutine(frame, bhav, CodeOwner, operand);
#if IDE_COMPAT
                if (Stack.LastOrDefault().GetCurrentInstruction().Breakpoint || ThreadBreak == VMThreadBreakMode.StepIn)
                {
                    Breakpoint(frame);
                    ContinueExecution = false;
                }
                else
#endif
                {
                    ContinueExecution = true;
                }

                return;
            }


            var primitive = Context.Primitives[opcode];
            if (primitive == null)
            {
                HandleResult(frame, instruction, VMPrimitiveExitCode.GOTO_TRUE);
                return;
            }

            VMPrimitiveHandler handler = primitive.GetHandler();
            var result = handler.Execute(frame, instruction.Operand);

            if (result != null)
            {
                HandleResult(frame, instruction, result);
            }
        }
コード例 #13
0
        public static string ParseDialogString(VMStackFrame context, string input, STR source)
        {
            int           state   = 0;
            StringBuilder command = new StringBuilder();
            StringBuilder output  = new StringBuilder();

            if (input == null)
            {
                return("Missing String!!!");
            }

            for (int i = 0; i < input.Length; i++)
            {
                if (state == 0)
                {
                    if (input[i] == '$')
                    {
                        state = 1; //start parsing string
                        command.Clear();
                    }
                    else
                    {
                        output.Append(input[i]);
                    }
                }
                else
                {
                    command.Append(input[i]);
                    if (i == input.Length - 1 || !CommandSubstrValid(command.ToString()))
                    {
                        if (i != input.Length - 1 || char.IsDigit(input[i]))
                        {
                            command.Remove(command.Length - 1, 1);
                            i--;
                        }

                        var     cmdString = command.ToString();
                        short[] values    = new short[3];
                        if (cmdString.Length > 1 && cmdString[cmdString.Length - 1] == ':')
                        {
                            try
                            {
                                if (cmdString == "DynamicStringLocal:")
                                {
                                    values[1] = -1;
                                    values[2] = -1;
                                    for (int j = 0; j < 3; j++)
                                    {
                                        char   next = input[++i];
                                        string num  = "";
                                        while (char.IsDigit(next))
                                        {
                                            num += next;
                                            next = (++i == input.Length) ? '!': input[i];
                                        }
                                        if (num == "")
                                        {
                                            values[j] = -1;
                                            if (j == 1)
                                            {
                                                values[2] = -1;
                                            }
                                            break;
                                        }
                                        values[j] = short.Parse(num);
                                        if (i == input.Length || next != ':')
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    char   next = input[++i];
                                    string num  = "";
                                    while (char.IsDigit(next))
                                    {
                                        num += next;
                                        next = (++i == input.Length) ? '!' : input[i];
                                    }
                                    values[0] = short.Parse(num);
                                }
                                i--;
                            }
                            catch (FormatException)
                            {
                            }
                        }
                        try
                        {
                            switch (cmdString)
                            {
                            case "Object":
                            case "DynamicObjectName":
                                output.Append(context.StackObject.ToString()); break;

                            case "Me":
                                output.Append(context.Caller.ToString()); break;

                            case "TempXL:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.TempXL, values[0]).ToString()); break;

                            case "MoneyXL:":
                                output.Append("$" + VMMemory.GetBigVariable(context, Scopes.VMVariableScope.TempXL, values[0]).ToString("##,#0")); break;

                            case "Temp:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Temps, values[0]).ToString()); break;

                            case "$":
                                output.Append("$"); i--; break;

                            case "Attribute:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.MyObjectAttributes, values[0]).ToString()); break;

                            case "DynamicStringLocal:":
                                STR res = null;
                                if (values[2] != -1 && values[1] != -1)
                                {
                                    VMEntity obj = context.VM.GetObjectById((short)context.Locals[values[2]]);
                                    if (obj == null)
                                    {
                                        break;
                                    }
                                    ushort tableID = (ushort)context.Locals[values[1]];

                                    {    //local
                                        if (obj.SemiGlobal != null)
                                        {
                                            res = obj.SemiGlobal.Get <STR>(tableID);
                                        }
                                        if (res == null)
                                        {
                                            res = obj.Object.Resource.Get <STR>(tableID);
                                        }
                                        if (res == null)
                                        {
                                            res = context.Global.Resource.Get <STR>(tableID);
                                        }
                                    }
                                }
                                else if (values[1] != -1)
                                {
                                    //global table
                                    ushort tableID = (ushort)context.Locals[values[1]];
                                    res = context.Global.Resource.Get <STR>(tableID);
                                }
                                else
                                {
                                    res = source;
                                }

                                ushort index = (ushort)context.Locals[values[0]];
                                if (res != null)
                                {
                                    var str = res.GetString(index);
                                    output.Append(ParseDialogString(context, str, res));     // recursive command parsing!
                                    // this is needed for the crafting table.
                                    // though it is also, completely insane?
                                }
                                break;

                            case "Local:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]).ToString()); break;

                            case "Param:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Parameters, values[0]).ToString()); break;

                            case "NameLocal:":
                                output.Append("(NameLocal)"); break;

                            default:
                                output.Append(cmdString);
                                break;
                            }
                        } catch (Exception)
                        {
                            //something went wrong. just skip command
                        }
                        state = 0;
                    }
                }
            }
            output.Replace("\r\n", "\r\n\r\n");
            return(output.ToString());
        }
コード例 #14
0
 public VMSimanticsException(string message, VMStackFrame context) : base(message)
 {
     this.context = context;
     this.message = message;
 }
コード例 #15
0
 public abstract VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand operand);