Esempio n. 1
0
        public void AddMethod(int i, ScenarioTag.ScriptMethodDefinition scriptMethod)
        {
            var modifiers = SyntaxTokenList.Create(Token(SyntaxKind.PublicKeyword))
                            .Add(Token(SyntaxKind.AsyncKeyword));

            TypeSyntax returnType = ParseTypeName("Task");

            if (scriptMethod.ReturnType != ScriptDataType.Void)
            {
                returnType = GenericName("Task").AddTypeArgumentListArguments(SyntaxUtil.ScriptTypeSyntax(scriptMethod.ReturnType));
            }

            var method = MethodDeclaration(
                returnType,
                SyntaxUtil.SanitizeIdentifier(scriptMethod.Description))
                         .WithModifiers(modifiers);

            // Push root method body as first scope
            var block     = new StatementBlockContext();
            var rootScope = new Scope(scriptMethod.ReturnType, block, block);
            var retScope  = EvaluateNodes(scriptMethod.SyntaxNodeIndex, rootScope);

            Debug.Assert(rootScope == retScope, "Last scope wasn't the provided root");

            methods.Add(method.WithBody(Block(block.GetInnerStatements()))
                        .AddAttributeLists(AttributeList(SeparatedList(new[] {
                Attribute(IdentifierName(nameof(ScriptMethodAttribute).Replace("Attribute", "")))
                .AddArgumentListArguments(
                    AttributeArgument(SyntaxUtil.LiteralExpression(i)),
                    AttributeArgument(MemberAccessExpression(
                                          SyntaxKind.SimpleMemberAccessExpression,
                                          IdentifierName(nameof(Lifecycle)),
                                          IdentifierName(scriptMethod.Lifecycle.ToString()))))
            }))));
        }
Esempio n. 2
0
        public StatementSyntax CreateWellKnownAssignment(TypeSyntax type,
                                                         string desiredName,
                                                         int itemIndex)
        {
            if (nameRepo.TryGetName(desiredName, nameof(ScenarioTag.EntityReference), itemIndex, out var name) == false)
            {
                throw new Exception("Unable to find property name");
            }

            ExpressionSyntax access = ElementAccessExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                     IdentifierName("scenarioTag"),
                                                                                     IdentifierName(nameof(ScenarioTag.WellKnownItems))))
                                      .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(itemIndex)));

            access = ObjectCreationExpression(
                GenericName(nameof(ScenarioEntity <object>))
                .AddTypeArgumentListArguments(type))
                     .AddArgumentListArguments(
                Argument(SyntaxUtil.LiteralExpression(itemIndex)),
                Argument(access));

            var exp = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                           IdentifierName(name),
                                           access);

            return(ExpressionStatement(exp));
        }
Esempio n. 3
0
        public void AddGlobalVariable(ScenarioTag.ScriptVariableDefinition variable)
        {
            Debug.Assert(variable.Value_H16 < scenario.ScriptSyntaxNodes.Length, "Variable expression is not valid");

            var node = scenario.ScriptSyntaxNodes[variable.Value_H16];

            Debug.Assert(node.Checkval == variable.Value_L16, "Variable expression checkval did not match");

            var expressionContext = new SingleExpressionStatementContext(null, variable.DataType);
            var defScope          = new Scope(variable.DataType, expressionContext, expressionContext);
            var retScope          = EvaluateNodes(variable.Value_H16, defScope);

            Debug.Assert(retScope == defScope, "Returned scope was not the provided root");

            var field = SyntaxUtil.CreateField(variable);

            fields.Add(field);

            var assignment = AssignmentExpression(
                SyntaxKind.SimpleAssignmentExpression,
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    ThisExpression(),
                    IdentifierName(field.Declaration.Variables.First().Identifier.ToString())),
                expressionContext.GetInnerExpression());

            constructorStatements.Add(ExpressionStatement(assignment));
        }
Esempio n. 4
0
        public void CreateDataInitializer(ScenarioTag scnr)
        {
            var scenarioParam = Identifier("scenarioTag");
            var sceneParam    = Identifier("scene");

            var statements = new List <StatementSyntax>();

            statements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(nameof(ScenarioScriptBase.Scenario))),
                                                                    IdentifierName(scenarioParam))));

            for (int i = 0; i < scnr.WellKnownItems.Length; i++)
            {
                var externalRef = scnr.WellKnownItems[i];

                if (externalRef.ItemType != ScenarioTag.WellKnownVarType.Undef && externalRef.Index != ushort.MaxValue)
                {
                    var varType = SyntaxUtil.WellKnownTypeSyntax(externalRef.ItemType);
                    statements.Add(CreateWellKnownAssignment(varType, externalRef.Identifier, i));
                }
            }

            AddSquadInitialization(statements, scnr);

            this.methods.Add(
                MethodDeclaration(
                    PredefinedType(Token(SyntaxKind.VoidKeyword)),
                    nameof(ScenarioScriptBase.InitializeData))
                .AddParameterListParameters(
                    Parameter(scenarioParam).WithType(ParseTypeName(nameof(ScenarioTag))),
                    Parameter(sceneParam).WithType(ParseTypeName(nameof(Scene))))
                .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.OverrideKeyword))
                .WithBody(Block(statements)));
        }
Esempio n. 5
0
        public ScriptLoader(string generatedScriptOutput = null)
        {
            var suppressions = new Dictionary <string, ReportDiagnostic>
            {
                { "CS1998", ReportDiagnostic.Suppress }
            };


            var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
                                                                  specificDiagnosticOptions: suppressions,
                                                                  optimizationLevel: OptimizationLevel.Debug,
                                                                  platform: Platform.AnyCpu);

            var baseLibPath = Path.GetDirectoryName(typeof(object).Assembly.Location);

            var tpa = (string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES");

            this.generatedScriptOutput = generatedScriptOutput;
            this.compilation           = CSharpCompilation.Create(AssemblyName, options: compilationOptions)
                                         .AddReferences(MetadataReference.CreateFromFile(typeof(ScriptLoader).Assembly.Location))
                                         .AddReferences(MetadataReference.CreateFromFile(Path.Combine(baseLibPath, "mscorlib.dll")))
                                         .AddReferences(MetadataReference.CreateFromFile(Path.Combine(baseLibPath, "System.dll")))
                                         .AddReferences(MetadataReference.CreateFromFile(Path.Combine(baseLibPath, "System.Core.dll")));

            foreach (var asmPath in tpa.Split(';'))
            {
                this.compilation = this.compilation.AddReferences(
                    MetadataReference.CreateFromFile(asmPath));
            }

            foreach (var reference in typeof(ScriptLoader).Assembly.GetReferencedAssemblies())
            {
                if (reference.CodeBase != null)
                {
                    compilation = compilation.AddReferences(MetadataReference.CreateFromFile(reference.CodeBase));
                }
            }

            var targetFrameworkUnit = SyntaxFactory.CompilationUnit()
                                      .AddAttributeLists(
                SyntaxFactory.AttributeList(
                    SyntaxFactory.SingletonSeparatedList(
                        SyntaxFactory.Attribute(SyntaxFactory.QualifiedName(
                                                    SyntaxFactory.QualifiedName(
                                                        SyntaxFactory.QualifiedName(
                                                            SyntaxFactory.IdentifierName("System"),
                                                            SyntaxFactory.IdentifierName("Runtime")),
                                                        SyntaxFactory.IdentifierName("Versioning")),
                                                    SyntaxFactory.IdentifierName("TargetFrameworkAttribute")))
                        .AddArgumentListArguments(
                            SyntaxFactory.AttributeArgument(SyntaxUtil.LiteralExpression(".NETStandard,Version=v2.1")),
                            SyntaxFactory.AttributeArgument(SyntaxUtil.LiteralExpression(""))
                            .WithNameEquals(SyntaxFactory.NameEquals(SyntaxFactory.IdentifierName("FrameworkDisplayName"))))))
                .WithTarget(SyntaxFactory.AttributeTargetSpecifier(SyntaxFactory.Token(SyntaxKind.AssemblyKeyword))));

            this.compilation = this.compilation.AddSyntaxTrees(targetFrameworkUnit.SyntaxTree);
        }
Esempio n. 6
0
        private void AddWellKnownPublicProperty(TypeSyntax type, string name, int itemIndex)
        {
            var propName = nameRepo.RegisterName(name, nameof(ScenarioTag.EntityReference), itemIndex);

            var propType = GenericName(nameof(ScenarioEntity <object>))
                           .AddTypeArgumentListArguments(type);

            var prop = PropertyDeclaration(propType, propName)
                       .WithAccessorList(SyntaxUtil.AutoPropertyAccessorList());

            properties.Add(prop.WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))));
        }
Esempio n. 7
0
        public string RegisterName(string desiredName, string dataType, int?index = null)
        {
            if (string.IsNullOrWhiteSpace(desiredName))
            {
                desiredName = "Unnamed";
            }

            var sanitized = SyntaxUtil.SanitizeMemberAccess(desiredName);

            var name = new RegisteredName()
            {
                OriginalName = desiredName,
                TypeInfo     = dataType,
                Index        = index,
            };

            var attempt     = 0;
            var attemptName = sanitized;

            var key = SimplifiedKey(desiredName, dataType, index);

            if (originalNameLookup.TryGetValue(key, out var nameSlot))
            {
                while (nameSlot.Any(n => n.UniqueName == attemptName) || finalNames.Contains(attemptName))
                {
                    attempt++;
                    attemptName = sanitized + attempt;
                }

                name.UniqueName = attemptName;
                nameSlot.Add(name);
            }
            else
            {
                while (finalNames.Contains(attemptName))
                {
                    attempt++;
                    attemptName = sanitized + attempt;
                }

                name.UniqueName = attemptName;
                originalNameLookup.Add(key, new List <RegisteredName>()
                {
                    name
                });
            }

            finalNames.Add(name.UniqueName);
            return(name.UniqueName);
        }
Esempio n. 8
0
        private void AddPublicProperty(ScriptDataType type, string name, int itemIndex)
        {
            var propName = nameRepo.RegisterName(name, type.ToString(), itemIndex);

            var scnrPropName = type switch
            {
                ScriptDataType.CameraPathTarget => nameof(ScenarioTag.CameraPathTargets),
                ScriptDataType.LocationFlag => nameof(ScenarioTag.LocationFlagDefinitions),
                ScriptDataType.CinematicTitle => nameof(ScenarioTag.CinematicTitleDefinitions),
                ScriptDataType.Trigger => nameof(ScenarioTag.TriggerVolumes),
                ScriptDataType.StartingProfile => nameof(ScenarioTag.StartingProfileDefinitions),
                ScriptDataType.DeviceGroup => nameof(ScenarioTag.DeviceGroupDefinitions),
                ScriptDataType.AI => nameof(ScenarioTag.AiSquadGroupDefinitions),
                ScriptDataType.AIOrders => nameof(ScenarioTag.AiOrderDefinitions),
                _ => throw new Exception("Not support!")
            };

            ExpressionSyntax access = ElementAccessExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                     IdentifierName(nameof(ScenarioScriptBase.Scenario)),
                                                                                     IdentifierName(scnrPropName)))
                                      .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(itemIndex)));

            var scnrProp = ScenarioTagProperties[scnrPropName];

            if (scnrProp.PropertyType.HasElementType &&
                scnrProp.PropertyType.GetElementType().GetInterfaces().Any(i =>
                                                                           i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IGameObjectDefinition <>)))
            {
                access = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                access,
                                                IdentifierName(nameof(IGameObjectDefinition <object> .GameObject)));
            }

            var prop = PropertyDeclaration(SyntaxUtil.ScriptTypeSyntax(type), propName)
                       .WithExpressionBody(ArrowExpressionClause(access))
                       .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));


            properties.Add(prop.WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))));
        }
Esempio n. 9
0
        public void Load(ScenarioTag scnr)
        {
            var scenarioParts = scnr.Name.Split('\\', StringSplitOptions.RemoveEmptyEntries)
                                .Select(p => p.Trim())
                                .ToArray();

            var repo = new MemberNameRepository();

            // Reserve class field and method names

            for (var i = 0; i < scnr.ScriptVariables.Length; i++)
            {
                var variable     = scnr.ScriptVariables[i];
                var returnedName = repo.RegisterName(variable.Description, variable.DataType.ToString(), i);
            }

            for (var i = 0; i < scnr.ScriptMethods.Length; i++)
            {
                var method       = scnr.ScriptMethods[i];
                var returnedName = repo.RegisterName(method.Description, ScriptDataType.ScriptReference.ToString(), i);
            }

            var baseFields = typeof(ScenarioScriptBase).GetFields();

            foreach (var field in baseFields)
            {
                var found = SyntaxUtil.TryGetScriptTypeFromType(field.FieldType, out var t);

                Debug.Assert(found);

                repo.RegisterName(field.Name, t.ToString());
            }

            // Generate data properties

            var dataGen = new ScriptCSharpGenerator(scnr, repo);

            dataGen.AddProperties(scnr);

            dataGen.CreateDataInitializer(scnr);

            var originAttr = SyntaxFactory.Attribute(
                SyntaxFactory.ParseName("OriginScenario"),
                SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(new[] {
                SyntaxFactory.AttributeArgument(
                    SyntaxFactory.LiteralExpression(
                        SyntaxKind.StringLiteralExpression,
                        SyntaxFactory.Literal(scnr.Name)))
            })));

            var classGen = new ScriptCSharpGenerator(scnr, repo, classAttributes: new[] { originAttr });

            foreach (var variable in scnr.ScriptVariables)
            {
                classGen.AddGlobalVariable(variable);
            }

            for (int i = 0; i < scnr.ScriptMethods.Length; i++)
            {
                classGen.AddMethod(i, scnr.ScriptMethods[i]);
            }

            this.AddCode($"{scenarioParts.Last()}.cs", classGen.Generate());
            this.AddCode($"{scenarioParts.Last()}.Data.cs", dataGen.Generate());
        }
Esempio n. 10
0
        public void AddProperties(ScenarioTag scnr)
        {
            for (int i = 0; i < scnr.WellKnownItems.Length; i++)
            {
                var externalRef = scnr.WellKnownItems[i];

                if (externalRef.ItemType == ScenarioTag.WellKnownVarType.Undef)
                {
                    continue;
                }

                var varType = SyntaxUtil.WellKnownTypeSyntax(externalRef.ItemType);

                AddWellKnownPublicProperty(varType, externalRef.Identifier, i);
            }

            for (int i = 0; i < scnr.CameraPathTargets.Length; i++)
            {
                var cam = scnr.CameraPathTargets[i];
                AddPublicProperty(ScriptDataType.CameraPathTarget, cam.Description, i);
            }

            CreateNestedSquadClasses(scnr);

            for (int i = 0; i < scnr.AiSquadGroupDefinitions.Length; i++)
            {
                var ai = scnr.AiSquadGroupDefinitions[i];
                AddPublicProperty(ScriptDataType.AI, ai.Description, i);
            }

            for (int i = 0; i < scnr.AiOrderDefinitions.Length; i++)
            {
                var order = scnr.AiOrderDefinitions[i];
                AddPublicProperty(ScriptDataType.AIOrders, order.Description, i);
            }

            for (int i = 0; i < scnr.LocationFlagDefinitions.Length; i++)
            {
                var flag = scnr.LocationFlagDefinitions[i];
                AddPublicProperty(ScriptDataType.LocationFlag, flag.Description, i);
            }

            for (int i = 0; i < scnr.CinematicTitleDefinitions.Length; i++)
            {
                var title = scnr.CinematicTitleDefinitions[i];
                AddPublicProperty(ScriptDataType.CinematicTitle, title.Title, i);
            }

            for (int i = 0; i < scnr.TriggerVolumes.Length; i++)
            {
                var tv = scnr.TriggerVolumes[i];
                AddPublicProperty(ScriptDataType.Trigger, tv.Description, i);
            }

            for (int i = 0; i < scnr.StartingProfileDefinitions.Length; i++)
            {
                var profile = scnr.StartingProfileDefinitions[i];
                AddPublicProperty(ScriptDataType.StartingProfile, profile.Description, i);
            }

            for (int i = 0; i < scnr.DeviceGroupDefinitions.Length; i++)
            {
                var group = scnr.DeviceGroupDefinitions[i];
                AddPublicProperty(ScriptDataType.DeviceGroup, group.Description, i);
            }
        }
Esempio n. 11
0
        // Make squads into nested classes
        public void CreateNestedSquadClasses(ScenarioTag tag)
        {
            for (var i = 0; i < tag.AiSquadDefinitions.Length; i++)
            {
                var squad = tag.AiSquadDefinitions[i];

                var squadPropName = nameRepo.RegisterName(squad.Description, ScriptDataType.AI.ToString(), i);

                var dataClassProps = new List <PropertyDeclarationSyntax>();
                dataClassProps.Add(SyntaxUtil.CreateProperty(ParseTypeName(nameof(ScenarioTag)), nameof(ScenarioTag)));

                var nestedRepo = new MemberNameRepository();

                var m = 0;
                foreach (var ai in squad.StartingLocations)
                {
                    var propName = nestedRepo.RegisterName(ai.Description, ScriptDataType.AI.ToString(), m);

                    ExpressionSyntax startingLocationAccess = ElementAccessExpression(
                        MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                               ElementAccessExpression(
                                                   MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                          IdentifierName(nameof(ScenarioTag)),
                                                                          IdentifierName(nameof(tag.AiSquadDefinitions))))
                                               .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(i))),
                                               IdentifierName(nameof(squad.StartingLocations))))
                                                              .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(m)));

                    dataClassProps.Add(PropertyDeclaration(SyntaxUtil.ScriptTypeSyntax(ScriptDataType.AI), propName)
                                       .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)))
                                       .WithExpressionBody(ArrowExpressionClause(startingLocationAccess))
                                       .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));

                    m++;
                }

                ExpressionSyntax squadAccess = ElementAccessExpression(
                    MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                           IdentifierName(nameof(ScenarioTag)),
                                           IdentifierName(nameof(tag.AiSquadDefinitions))))
                                               .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(i)));

                // This is so the script can reference the squad itself, need special init handling
                dataClassProps.Add(PropertyDeclaration(SyntaxUtil.ScriptTypeSyntax(ScriptDataType.AI), "Squad")
                                   .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)))
                                   .WithExpressionBody(ArrowExpressionClause(squadAccess))
                                   .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));

                var squadTypeName = "Squad_" + squadPropName;

                var cls = ClassDeclaration(squadTypeName)
                          .AddModifiers(Token(SyntaxKind.PublicKeyword))
                          .WithMembers(new SyntaxList <MemberDeclarationSyntax>(dataClassProps))
                          .AddMembers(ConstructorDeclaration(squadTypeName)
                                      .AddModifiers(Token(SyntaxKind.PublicKeyword))
                                      .AddParameterListParameters(
                                          Parameter(Identifier(nameof(ScenarioTag)))
                                          .WithType(ParseTypeName(nameof(ScenarioTag))))
                                      .WithBody(Block(new List <StatementSyntax>()
                {
                    ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                             MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                    ThisExpression(),
                                                                                    IdentifierName(nameof(ScenarioTag))),
                                                             IdentifierName(nameof(ScenarioTag))))
                })));

                nestedDataClasses.Add(cls);
                nameRepo.NestedRepos.Add(squadPropName, nestedRepo);

                properties.Add(PropertyDeclaration(ParseTypeName(squadTypeName), squadPropName)
                               .AddModifiers(Token(SyntaxKind.PublicKeyword))
                               .WithAccessorList(SyntaxUtil.AutoPropertyAccessorList()));
            }
        }