コード例 #1
0
ファイル: GameAttribute.cs プロジェクト: loonbg/mooege
 public GameAttributeDependency(GameAttribute attribute, int? key, bool usesExplicitKey,
     bool isManualDependency)
 {
     Attribute = attribute;
     Key = key;
     UsesExplicitKey = usesExplicitKey;
     IsManualDependency = isManualDependency;
 }
コード例 #2
0
ファイル: GameAttribute.cs プロジェクト: wlasser/mooege-2
 public GameAttributeDependency(GameAttribute attribute, int?key, bool usesExplicitKey,
                                bool isManualDependency)
 {
     Attribute          = attribute;
     Key                = key;
     UsesExplicitKey    = usesExplicitKey;
     IsManualDependency = isManualDependency;
 }
コード例 #3
0
ファイル: GameAttributeMap.cs プロジェクト: venci17/mooege
        private void RawSetAttributeValue(GameAttribute attribute, int? key, GameAttributeValue value)
        {
            KeyId keyid;
            keyid.Id = attribute.Id;
            keyid.Key = key;

            _attributeValues[keyid] = value;

            if (!_changedAttributes.Contains(keyid))
                _changedAttributes.Add(keyid);

            // mark dependant attributes as changed
            if (attribute.Dependents != null)
            {
                foreach (var dependent in attribute.Dependents)
                {
                    int? usekey;

                    if (dependent.IsManualDependency)
                        usekey = dependent.Key;
                    else
                        usekey = dependent.UsesExplicitKey ? null : key;

                    if (dependent.IsManualDependency || dependent.UsesExplicitKey == false || dependent.Key == key)
                    {
                        // TODO: always update dependent values for now, but eventually make this lazy
                        RawSetAttributeValue(dependent.Attribute, usekey, dependent.Attribute.ScriptFunc(this, usekey));
                    }
                }
            }
        }
コード例 #4
0
ファイル: GameAttributeMap.cs プロジェクト: venci17/mooege
        private void SetAttributeValue(GameAttribute attribute, int? key, GameAttributeValue value)
        {
            // error if scripted attribute and is not settable
            if (attribute.ScriptFunc != null && !attribute.ScriptedAndSettable)
            {
                var frame = new System.Diagnostics.StackFrame(2, true);
                Logger.Error("illegal value assignment for GameAttribute.{0} attempted at {1}:{2}",
                    attribute.Name, frame.GetFileName(), frame.GetFileLineNumber());
            }

            if (attribute.EncodingType == GameAttributeEncoding.IntMinMax)
            {
                if (value.Value < attribute.Min.Value || value.Value > attribute.Max.Value)
                    throw new ArgumentOutOfRangeException("GameAttribute." + attribute.Name.Replace(' ', '_'), "Min: " + attribute.Min.Value + " Max: " + attribute.Max.Value + " Tried to set: " + value.Value);
            }
            else if (attribute.EncodingType == GameAttributeEncoding.Float16)
            {
                if (value.ValueF < GameAttribute.Float16Min || value.ValueF > GameAttribute.Float16Max)
                    throw new ArgumentOutOfRangeException("GameAttribute." + attribute.Name.Replace(' ', '_'), "Min: " + GameAttribute.Float16Min + " Max " + GameAttribute.Float16Max + " Tried to set: " + value.ValueF);
            }

            RawSetAttributeValue(attribute, key, value);
        }
コード例 #5
0
ファイル: GameAttributeMap.cs プロジェクト: venci17/mooege
        private GameAttributeValue RawGetAttributeValue(GameAttribute attribute, int? key)
        {
            KeyId keyid;
            keyid.Id = attribute.Id;
            keyid.Key = key;

            GameAttributeValue gaValue;
            if (_attributeValues.TryGetValue(keyid, out gaValue))
                return gaValue;
            return attribute._DefaultValue;
        }
コード例 #6
0
ファイル: GameAttributeMap.cs プロジェクト: venci17/mooege
 private GameAttributeValue GetAttributeValue(GameAttribute attribute, int? key)
 {
     if (attribute.ScriptFunc != null)
         return attribute.ScriptFunc(this, key);
     else
         return RawGetAttributeValue(attribute, key);
 }
コード例 #7
0
ファイル: GameAttributeMap.cs プロジェクト: Sanchen/mooege
        void SetAttributeValue(GameAttribute attribute, int? key, GameAttributeValue value)
        {
            KeyId keyid;
            keyid.Id = attribute.Id;
            keyid.Key = key;

            if (attribute.EncodingType == GameAttributeEncoding.IntMinMax)
            {
                if (value.Value < attribute.Min.Value || value.Value > attribute.Max.Value)
                    throw new ArgumentOutOfRangeException("GameAttribute." + attribute.Name.Replace(' ', '_'), "Min: " + attribute.Min.Value + " Max: " + attribute.Max.Value + " Tried to set: " + value.Value);
            }
            else if (attribute.EncodingType == GameAttributeEncoding.Float16)
            {
                if (value.ValueF < GameAttribute.Float16Min || value.ValueF > GameAttribute.Float16Max)
                    throw new ArgumentOutOfRangeException("GameAttribute." + attribute.Name.Replace(' ', '_'), "Min: " + GameAttribute.Float16Min  + " Max " + GameAttribute.Float16Max + " Tried to set: " + value.ValueF);
            }
            _attributeValues[keyid] = value;
        }
コード例 #8
0
ファイル: GameAttributeMap.cs プロジェクト: loonbg/mooege
 public int?[] AttributeKeys(GameAttribute ga)
 {
     return _attributeValues.Where(av => av.Key.Id == ga.Id).Select(av => av.Key.Key).ToArray();
 }
コード例 #9
0
        public static void ProcessAttributes(GameAttribute[] attributes)
        {
            // build string -> GameAttribute lookup
            var attributeLookup = attributes.ToDictionary(attr => attr.Name);
            // will contain C# code for the func<> body that represents each attribute's script.
            var csharpScripts = new Dictionary <GameAttribute, string>();

            // generate C#-compatible source lines from scripts and create attribute dependency lists
            foreach (GameAttribute attr in attributes)
            {
                // check for valid script in the attribute and select it
                string script;

                if (attr.ScriptA.Length > 0 && attr.ScriptA != "0")
                {
                    script = attr.ScriptA;
                }
                else if (attr.ScriptB.Length > 0 && attr.ScriptB != "0")
                {
                    script = attr.ScriptB;
                }
                else
                {
                    continue;  // no valid script, done processing this attribute
                }
                // by default all scripts are not settable
                // can be set to true if self-referring identifier is found
                attr.ScriptedAndSettable = false;

                // replace attribute references with GameAttributeMap lookups
                // also record all attributes used by script into each attribute's dependency list
                script = Regex.Replace(script, @"([A-Za-z_]\w*)(\.Agg)?(\#[A-Za-z_]\w*)?(?=[^\(\w]|\z)( \?)?",
                                       (match) =>
                {
                    // lookup attribute object
                    string identifierName = match.Groups[1].Value;
                    if (!attributeLookup.ContainsKey(identifierName))
                    {
                        throw new ScriptedAttributeInitializerError("invalid identifer parsed: " + identifierName);
                    }

                    GameAttribute identifier = attributeLookup[identifierName];

                    // key selection
                    int?key              = null;
                    string keyString     = "_key";
                    bool usesExplicitKey = false;

                    if (match.Groups[3].Success)
                    {
                        switch (match.Groups[3].Value.ToUpper())
                        {
                        case "#NONE": key = null; break;

                        case "#PHYSICAL": key = 0; break;

                        case "#FIRE": key = 1; break;

                        case "#LIGHTNING": key = 2; break;

                        case "#COLD": key = 3; break;

                        case "#POISON": key = 4; break;

                        case "#ARCANE": key = 5; break;

                        case "#HOLY": key = 6; break;

                        default:
                            throw new ScriptedAttributeInitializerError("error processing attribute script, invalid key in identifier: " + match.Groups[3].Value);
                        }

                        if (key == null)
                        {
                            keyString = "null";
                        }
                        else
                        {
                            keyString = key.ToString();
                        }

                        usesExplicitKey = true;
                    }

                    // add comparsion for int attributes that are directly used in an ?: expression.
                    string compare = "";
                    if (match.Groups[4].Success)
                    {
                        compare = identifier is GameAttributeI ? " > 0 ?" : " ?";
                    }

                    // handle self-referring lookup. example: Resource.Agg
                    if (match.Groups[2].Success)
                    {
                        attr.ScriptedAndSettable = true;
                        return("_map._RawGetAttribute(GameAttribute." + identifierName
                               + ", " + keyString + ")" + compare);
                    }

                    // record dependency
                    if (identifier.Dependents == null)
                    {
                        identifier.Dependents = new List <GameAttributeDependency>();
                    }

                    identifier.Dependents.Add(new GameAttributeDependency(attr, key, usesExplicitKey, false));

                    // generate normal lookup
                    return("_map[GameAttribute." + identifierName + ", " + keyString + "]" + compare);
                });

                // transform function calls into C# equivalents
                script = Regex.Replace(script, @"floor\(", "(float)Math.Floor(", RegexOptions.IgnoreCase);
                script = Regex.Replace(script, @"max\(", "Math.Max(", RegexOptions.IgnoreCase);
                script = Regex.Replace(script, @"min\(", "Math.Min(", RegexOptions.IgnoreCase);
                script = Regex.Replace(script, @"pin\(", "ScriptedAttributeInitializer.Pin(", RegexOptions.IgnoreCase);

                // add C# single-precision affix to decimal literals. example: 1.25 => 1.25f
                script = Regex.Replace(script, @"\d+\.\d+", "$0f");

                csharpScripts[attr] = script;
            }

            // generate and write final C# code to file
            string sourcePathBase = Path.Combine(Path.GetTempPath(), "MooegeScriptedAttributeFuncs");

            using (StreamWriter fout = new StreamWriter(sourcePathBase + ".cs"))
            {
                fout.Write(
                    @"// This file was auto-generated by Mooege class ScriptedAttributeInitializer
// It contains Funcs derived from GameAttribute.ScriptA/B scripts.
// Funcs will be assigned to their respective GameAttribute.ScriptFunc member.
using System;
using Mooege.Net.GS.Message;
using Mooege.Core.GS.Objects;

namespace Mooege.Net.GS.Message.GeneratedCode
{
    public class ScriptedAttributeFuncs
    {
");
                foreach (var scriptEntry in csharpScripts)
                {
                    // select output type cast to ensure it matches attribute type
                    string castType = scriptEntry.Key is GameAttributeF ? "float" : "int";

                    // write out full Func static class field
                    fout.WriteLine("        public static Func<GameAttributeMap, int?, GameAttributeValue> {0} = (_map, _key) => new GameAttributeValue(({1})({2}));",
                                   scriptEntry.Key.Name,
                                   castType,
                                   scriptEntry.Value);
                }

                fout.Write(
                    @"    }
}
");
            }

            // compile code
            var options = new CompilerParameters();

            options.GenerateExecutable      = false;
            options.OutputAssembly          = sourcePathBase + ".dll";
            options.IncludeDebugInformation = true;
            options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            var results = new CSharpCodeProvider().CompileAssemblyFromFile(options, sourcePathBase + ".cs");

            if (results.Errors.Count > 0)
            {
                StringBuilder emsg = new StringBuilder();
                emsg.AppendLine("encountered errors compiling attribute funcs:");
                foreach (var e in results.Errors)
                {
                    emsg.AppendLine(e.ToString());
                }

                throw new ScriptedAttributeInitializerError(emsg.ToString());
            }

            // pull funcs from new assembly and assign them to their respective attributes
            Type funcs = results.CompiledAssembly.GetType("Mooege.Net.GS.Message.GeneratedCode.ScriptedAttributeFuncs");

            foreach (var attr in csharpScripts.Keys)
            {
                attr.ScriptFunc = (Func <GameAttributeMap, int?, GameAttributeValue>)funcs
                                  .GetField(attr.Name).GetValue(null);
            }
        }
コード例 #10
0
        public static void ProcessAttributes(GameAttribute[] attributes)
        {
            // build string -> GameAttribute lookup
            var attributeLookup = attributes.ToDictionary(attr => attr.Name);
            // will contain C# code for the func<> body that represents each attribute's script.
            var csharpScripts = new Dictionary<GameAttribute, string>();

            // generate C#-compatible source lines from scripts and create attribute dependency lists
            foreach (GameAttribute attr in attributes)
            {
                // check for valid script in the attribute and select it
                string script;

                if (attr.ScriptA.Length > 0 && attr.ScriptA != "0")
                    script = attr.ScriptA;
                else if (attr.ScriptB.Length > 0 && attr.ScriptB != "0")
                    script = attr.ScriptB;
                else
                    continue;  // no valid script, done processing this attribute

                // by default all scripts are not settable
                // can be set to true if self-referring identifier is found
                attr.ScriptedAndSettable = false;

                // replace attribute references with GameAttributeMap lookups
                // also record all attributes used by script into each attribute's dependency list
                script = Regex.Replace(script, @"([A-Za-z_]\w*)(\.Agg)?(\#[A-Za-z_]\w*)?(?=[^\(\w]|\z)( \?)?",
                    (match) =>
                    {
                        // lookup attribute object
                        string identifierName = match.Groups[1].Value;
                        if (!attributeLookup.ContainsKey(identifierName))
                            throw new ScriptedAttributeInitializerError("invalid identifer parsed: " + identifierName);

                        GameAttribute identifier = attributeLookup[identifierName];

                        // key selection
                        int? key = null;
                        string keyString = "_key";
                        bool usesExplicitKey = false;

                        if (match.Groups[3].Success)
                        {
                            switch (match.Groups[3].Value.ToUpper())
                            {
                                case "#NONE": key = null; break;
                                case "#PHYSICAL": key = 0; break;
                                case "#FIRE": key = 1; break;
                                case "#LIGHTNING": key = 2; break;
                                case "#COLD": key = 3; break;
                                case "#POISON": key = 4; break;
                                case "#ARCANE": key = 5; break;
                                case "#HOLY": key = 6; break;
                                default:
                                    throw new ScriptedAttributeInitializerError("error processing attribute script, invalid key in identifier: " + match.Groups[3].Value);
                            }

                            if (key == null)
                                keyString = "null";
                            else
                                keyString = key.ToString();

                            usesExplicitKey = true;
                        }

                        // add comparsion for int attributes that are directly used in an ?: expression.
                        string compare = "";
                        if (match.Groups[4].Success)
                            compare = identifier is GameAttributeI ? " > 0 ?" : " ?";

                        // handle self-referring lookup. example: Resource.Agg
                        if (match.Groups[2].Success)
                        {
                            attr.ScriptedAndSettable = true;
                            return "_map._RawGetAttribute(GameAttribute." + identifierName
                                + ", " + keyString + ")" + compare;
                        }

                        // record dependency
                        if (identifier.Dependents == null)
                            identifier.Dependents = new List<GameAttributeDependency>();

                        identifier.Dependents.Add(new GameAttributeDependency(attr, key, usesExplicitKey, false));

                        // generate normal lookup
                        return "_map[GameAttribute." + identifierName + ", " + keyString + "]" + compare;
                    });

                // transform function calls into C# equivalents
                script = Regex.Replace(script, @"floor\(", "(float)Math.Floor(", RegexOptions.IgnoreCase);
                script = Regex.Replace(script, @"max\(", "Math.Max(", RegexOptions.IgnoreCase);
                script = Regex.Replace(script, @"min\(", "Math.Min(", RegexOptions.IgnoreCase);
                script = Regex.Replace(script, @"pin\(", "ScriptedAttributeInitializer.Pin(", RegexOptions.IgnoreCase);

                // add C# single-precision affix to decimal literals. example: 1.25 => 1.25f
                script = Regex.Replace(script, @"\d+\.\d+", "$0f");

                csharpScripts[attr] = script;
            }

            // generate and write final C# code to file
            string sourcePathBase = Path.Combine(Path.GetTempPath(), "MooegeScriptedAttributeFuncs");

            using (StreamWriter fout = new StreamWriter(sourcePathBase + ".cs"))
            {
                fout.Write(
@"// This file was auto-generated by Mooege class ScriptedAttributeInitializer
// It contains Funcs derived from GameAttribute.ScriptA/B scripts.
// Funcs will be assigned to their respective GameAttribute.ScriptFunc member.
using System;
using Mooege.Net.GS.Message;
using Mooege.Core.GS.Objects;

namespace Mooege.Net.GS.Message.GeneratedCode
{
    public class ScriptedAttributeFuncs
    {
");
                foreach (var scriptEntry in csharpScripts)
                {
                    // select output type cast to ensure it matches attribute type
                    string castType = scriptEntry.Key is GameAttributeF ? "float" : "int";

                    // write out full Func static class field
                    fout.WriteLine("        public static Func<GameAttributeMap, int?, GameAttributeValue> {0} = (_map, _key) => new GameAttributeValue(({1})({2}));",
                        scriptEntry.Key.Name,
                        castType,
                        scriptEntry.Value);
                }

                fout.Write(
@"    }
}
");
            }

            // compile code
            var options = new CompilerParameters();
            options.GenerateExecutable = false;
            options.OutputAssembly = sourcePathBase + ".dll";
            options.IncludeDebugInformation = true;
            options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            var results = new CSharpCodeProvider().CompileAssemblyFromFile(options, sourcePathBase + ".cs");
            if (results.Errors.Count > 0)
            {
                StringBuilder emsg = new StringBuilder();
                emsg.AppendLine("encountered errors compiling attribute funcs:");
                foreach (var e in results.Errors)
                    emsg.AppendLine(e.ToString());

                throw new ScriptedAttributeInitializerError(emsg.ToString());
            }

            // pull funcs from new assembly and assign them to their respective attributes
            Type funcs = results.CompiledAssembly.GetType("Mooege.Net.GS.Message.GeneratedCode.ScriptedAttributeFuncs");

            foreach (var attr in csharpScripts.Keys)
            {
                attr.ScriptFunc = (Func<GameAttributeMap, int?, GameAttributeValue>)funcs
                    .GetField(attr.Name).GetValue(null);
            }
        }