Beispiel #1
0
        private static UndertaleInstruction.Reference <UndertaleVariable> ParseVariableReference(string line, IList <UndertaleVariable> vars, Dictionary <string, UndertaleVariable> localvars, ref UndertaleInstruction.InstanceType instance, UndertaleInstruction instr, UndertaleData data = null)
        {
            string str = line;

            UndertaleInstruction.VariableType type         = UndertaleInstruction.VariableType.Normal;
            UndertaleInstruction.InstanceType realinstance = instance;
            if (str[0] != '[')
            {
                string inst    = null;
                int    instdot = str.IndexOf('.');
                if (instdot >= 0)
                {
                    inst = str.Substring(0, instdot);
                    str  = str.Substring(instdot + 1);
                    if (inst == "")
                    {
                        throw new Exception("Whoops?");
                    }
                }
                if (inst != null)
                {
                    short instnum;
                    if (Int16.TryParse(inst, out instnum))
                    {
                        instance = (UndertaleInstruction.InstanceType)instnum;
                    }
                    else
                    {
                        instance = (UndertaleInstruction.InstanceType)Enum.Parse(typeof(UndertaleInstruction.InstanceType), inst, true);
                    }
                }
                else
                {
                    instance = UndertaleInstruction.InstanceType.Undefined;
                }

                realinstance = instance;
                if (realinstance >= 0)
                {
                    realinstance = UndertaleInstruction.InstanceType.Self;
                }
                else if (realinstance == UndertaleInstruction.InstanceType.Other)
                {
                    realinstance = UndertaleInstruction.InstanceType.Self;
                }
                else if (realinstance == UndertaleInstruction.InstanceType.Arg)
                {
                    realinstance = UndertaleInstruction.InstanceType.Builtin;
                }
                else if (realinstance == UndertaleInstruction.InstanceType.Builtin)
                {
                    realinstance = UndertaleInstruction.InstanceType.Self; // used with @@This@@
                }
                else if (realinstance == UndertaleInstruction.InstanceType.Stacktop)
                {
                    realinstance = UndertaleInstruction.InstanceType.Self; // used with @@GetInstance@@
                }
            }
            else
            {
                int typeend = str.IndexOf(']');
                if (typeend >= 0)
                {
                    string typestr = str.Substring(1, typeend - 1);
                    str  = str.Substring(typeend + 1);
                    type = (UndertaleInstruction.VariableType)Enum.Parse(typeof(UndertaleInstruction.VariableType), typestr, true);

                    int instanceEnd = str.IndexOf('.');
                    if (instanceEnd >= 0)
                    {
                        string instancestr = str.Substring(0, instanceEnd);
                        str          = str.Substring(instanceEnd + 1);
                        realinstance = (UndertaleInstruction.InstanceType)Enum.Parse(typeof(UndertaleInstruction.InstanceType), instancestr, true);
                    }
                    else
                    {
                        if (type == UndertaleInstruction.VariableType.Array ||
                            type == UndertaleInstruction.VariableType.StackTop)
                        {
                            throw new Exception("Old instruction format is incompatible (missing instance type in array or stacktop)");
                        }

                        if (realinstance >= 0)
                        {
                            realinstance = UndertaleInstruction.InstanceType.Self;
                        }
                        else if (realinstance == UndertaleInstruction.InstanceType.Other)
                        {
                            realinstance = UndertaleInstruction.InstanceType.Self;
                        }
                    }
                }
                else
                {
                    throw new Exception("Missing ']' character in variable reference");
                }
            }

            if (data?.GeneralInfo?.BytecodeVersion <= 14)
            {
                realinstance = UndertaleInstruction.InstanceType.Undefined;
            }

            UndertaleVariable varobj;

            if (realinstance == UndertaleInstruction.InstanceType.Local)
            {
                varobj = localvars.ContainsKey(str) ? localvars[str] : null;
            }
            else
            {
                varobj = vars.Where((x) => x.Name.Content == str && x.InstanceType == realinstance).FirstOrDefault();
            }
            if (varobj == null)
            {
                throw new Exception("Bad variable: " + realinstance.ToString().ToLower() + "." + str);
            }
            return(new UndertaleInstruction.Reference <UndertaleVariable>(varobj, type));
        }
        private static UndertaleInstruction.Reference <UndertaleVariable> ParseVariableReference(string line, IList <UndertaleVariable> vars, Dictionary <string, UndertaleVariable> localvars, ref UndertaleInstruction.InstanceType instance, UndertaleInstruction instr, Func <int, UndertaleInstruction.InstanceType?> lookOnStack = null, UndertaleData data = null)
        {
            string str     = line;
            string inst    = null;
            int    instdot = str.IndexOf('.');

            if (instdot >= 0)
            {
                inst = str.Substring(0, instdot);
                str  = str.Substring(instdot + 1);
                if (inst == "")
                {
                    throw new Exception("Whoops?");
                }
            }
            if (inst != null)
            {
                short instnum;
                if (Int16.TryParse(inst, out instnum))
                {
                    instance = (UndertaleInstruction.InstanceType)instnum;
                }
                else
                {
                    instance = (UndertaleInstruction.InstanceType)Enum.Parse(typeof(UndertaleInstruction.InstanceType), inst, true);
                }
            }
            else
            {
                instance = UndertaleInstruction.InstanceType.Undefined;
            }
            UndertaleInstruction.VariableType type = UndertaleInstruction.VariableType.Normal;
            if (str[0] == '[')
            {
                int typeend = str.IndexOf(']');
                if (typeend >= 0)
                {
                    string typestr = str.Substring(1, typeend - 1);
                    str  = str.Substring(typeend + 1);
                    type = (UndertaleInstruction.VariableType)Enum.Parse(typeof(UndertaleInstruction.VariableType), typestr, true);
                }
            }

            UndertaleInstruction.InstanceType realinstance = instance;
            // for arrays, the type is on the stack which totally breaks things
            // This is an ugly hack to handle that
            // see https://github.com/krzys-h/UndertaleModTool/issues/27#issuecomment-426637438
            if (type == UndertaleInstruction.VariableType.Array && lookOnStack != null)
            {
                var instTypeOnStack = lookOnStack(instr.Kind == UndertaleInstruction.Opcode.Pop && instr.Type1 == UndertaleInstruction.DataType.Int32 ? 3 : 2);
                if (instTypeOnStack.HasValue)
                {
                    realinstance = instTypeOnStack.Value;
                }
            }
            if (realinstance >= 0)
            {
                realinstance = UndertaleInstruction.InstanceType.Self;
            }
            else if (realinstance == UndertaleInstruction.InstanceType.Other)
            {
                realinstance = UndertaleInstruction.InstanceType.Self;
            }

            if (data?.GeneralInfo?.BytecodeVersion <= 14)
            {
                realinstance = UndertaleInstruction.InstanceType.Undefined;
            }

            UndertaleVariable varobj;

            if (realinstance == UndertaleInstruction.InstanceType.Local)
            {
                varobj = localvars.ContainsKey(str) ? localvars[str] : null;
            }
            else
            {
                varobj = vars.Where((x) => x.Name.Content == str && x.InstanceType == realinstance).FirstOrDefault();
            }
            if (varobj == null)
            {
                throw new Exception("Bad variable: " + realinstance.ToString().ToLower() + "." + str);
            }
            return(new UndertaleInstruction.Reference <UndertaleVariable>(varobj, type));
        }
Beispiel #3
0
        private static UndertaleInstruction.Reference <UndertaleVariable> ParseVariableReference(string line, IList <UndertaleVariable> vars, Dictionary <string, UndertaleVariable> localvars, ref UndertaleInstruction.InstanceType instance, UndertaleInstruction.InstanceType?prevInstType)
        {
            string str     = line;
            string inst    = null;
            int    instdot = str.IndexOf('.');

            if (instdot >= 0)
            {
                inst = str.Substring(0, instdot);
                str  = str.Substring(instdot + 1);
                if (inst == "")
                {
                    throw new Exception("Whoops?");
                }
            }
            if (inst != null)
            {
                short instnum;
                if (Int16.TryParse(inst, out instnum))
                {
                    instance = (UndertaleInstruction.InstanceType)instnum;
                }
                else
                {
                    instance = (UndertaleInstruction.InstanceType)Enum.Parse(typeof(UndertaleInstruction.InstanceType), inst, true);
                }
            }
            else
            {
                instance = UndertaleInstruction.InstanceType.Undefined;
            }
            UndertaleInstruction.VariableType type = UndertaleInstruction.VariableType.Normal;
            if (str[0] == '[')
            {
                int typeend = str.IndexOf(']');
                if (typeend >= 0)
                {
                    string typestr = str.Substring(1, typeend - 1);
                    str  = str.Substring(typeend + 1);
                    type = (UndertaleInstruction.VariableType)Enum.Parse(typeof(UndertaleInstruction.VariableType), typestr, true);
                }
            }

            UndertaleInstruction.InstanceType realinstance = instance;
            // for arrays, the type is on the stack which totally breaks things
            // This is an ugly hack to handle that
            if (type == UndertaleInstruction.VariableType.Array && prevInstType.HasValue)
            {
                realinstance = prevInstType.Value;
            }
            if (realinstance >= 0)
            {
                realinstance = UndertaleInstruction.InstanceType.Self;
            }


            UndertaleVariable varobj;

            if (realinstance == UndertaleInstruction.InstanceType.Local)
            {
                varobj = localvars.ContainsKey(str) ? localvars[str] : null;
            }
            else
            {
                varobj = vars.Where((x) => x.Name.Content == str && x.InstanceType == realinstance).FirstOrDefault();
            }
            if (varobj == null)
            {
                throw new Exception("Bad variable!");
            }
            return(new UndertaleInstruction.Reference <UndertaleVariable>(varobj, type));
        }