Esempio n. 1
0
        internal static object CreateRef(Type resType, IDef res)
        {
            var type = typeof(DefRef <>).MakeGenericType(resType);
            // ReSharper disable once PossibleNullReferenceException
            var retVal = type.GetConstructor(new[] { resType }).Invoke(new object[] { res });

            return(retVal);
        }
Esempio n. 2
0
 public static Type GetTypeFromDef(IDef def)
 {
     if (def == null)
     {
         return(null);
     }
     return(_defToInstanceType[def.GetType()]);
 }
Esempio n. 3
0
 public static Type GetDefFromSceneDef(IDef sceneDef)
 {
     if (sceneDef == null)
     {
         return(null);
     }
     if (!_sceneDefToInstanceType.TryGetValue(sceneDef.GetType(), out var instanceType))
     {
         return(null);
     }
     _instanceTypeToDef.TryGetValue(instanceType, out var def);
     return(def);
 }
Esempio n. 4
0
 public static Type GetSceneDefFromDef(IDef def)
 {
     if (def == null)
     {
         return(null);
     }
     if (!_defToInstanceType.TryGetValue(def.GetType(), out var instanceType))
     {
         return(null);
     }
     _instanceTypeToSceneDef.TryGetValue(instanceType, out var sceneDef);
     return(sceneDef);
 }
Esempio n. 5
0
 public bool Equals(IDef <string> def) => def.Id.Equals(Id);
Esempio n. 6
0
 public DefIDFull GetID(IDef res) => LoadedResources.GetID(res);
Esempio n. 7
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            while (reader.TokenType == JsonToken.Comment)
            {
                reader.Read();
            }
            var context = (LoadingContext)serializer.Context.Context;

            var tokenType   = reader.TokenType;
            var readerValue = reader.Value;
            var lineInfo    = reader as IJsonLineInfo;
            var defType     = objectType.GetGenericArguments()[0];

            if (tokenType == JsonToken.Null)
            {
                return(CreateRef(defType, null));
            }
            if (tokenType == JsonToken.String)
            {
                var stringRef = readerValue as string;
                if (stringRef.StartsWith("/"))
                {
                    //this is an absolute reference to a resource
                    //if I'm loading a prototype and this is not an embedded prototype then I'm loading external prototype, I should not do anything here until I encounter it again
                    //next time it won't be a child proto file
                    if (context.IsProtoChildFile && !context.ProtoStack.Peek().Embedded)
                    {
                        var rRef = CreateRef(context.IsProto, defType, stringRef);
                        return(rRef);
                    }
                    if (context.IsProto)
                    {
                        context.PushProto(false);
                        var normRef = CreateRef(context.IsProto, defType, stringRef);
                        context.PopProto();
                        return(normRef);
                    }
                    return(CreateRef(context.IsProto, defType, stringRef));
                }
                else if (stringRef.StartsWith("./"))
                {
                    //this is a relative reference to a resource
                    if (context.IsProtoChildFile && !context.ProtoStack.Peek().Embedded)
                    {
                        var rRef = CreateRef(context.IsProto, defType, stringRef, context.RootAddress);
                        return(rRef);
                    }
                    if (context.IsProto)
                    {
                        context.PushProto(false);
                        var normRef = CreateRef(context.IsProto, defType, stringRef, context.RootAddress);
                        context.PopProto();
                        return(normRef);
                    }
                    return(CreateRef(context.IsProto, defType, stringRef, context.RootAddress));
                }
                else if (stringRef.StartsWith("$"))
                {
                    //this is a local reference to a resource
                    var  id  = stringRef.Substring(1);
                    IDef res = context.GetInternalRes(id);
                    if (res != null)
                    {
                        return(CreateRef(defType, res));
                    }
                    else
                    {
                        throw new JsonException($"Reference to internal def not found {stringRef} {lineInfo.LineNumber} {lineInfo.LinePosition} {context.RootAddress}");
                    }
                }
                else if (stringRef.StartsWith("@"))
                {
                    //this a reference to a variable
                    var    name = stringRef.Substring(1);
                    Type   t;
                    object var = context.GetVar(name, out t);
                    if (var == null)
                    {
                        Logger.Warn($"Variable has no value {stringRef} {lineInfo.LineNumber} {lineInfo.LinePosition} {context.RootAddress}");
                        return(CreateRef(defType, null));
                    }
                    else if (var is IRefBase)
                    {
                        try
                        {
                            return(ConvertToProperRef(var, defType));
                        }
                        catch (Exception e)
                        {
                            throw new JsonException($"Error converting ref variable type {stringRef} at {lineInfo.LineNumber} {lineInfo.LinePosition} {context.RootAddress}", e);
                        }
                    }
                    else
                    {
                        var attr = defType.GetCustomAttribute <CanBeCreatedFromAliasedPrimitiveAttribute>(inherit: true);
                        if (attr != null)
                        {
                            var objectOfDesiredType = PrimitiveTypesConverter.Convert(var, attr.PrimitiveType);
                            var def = defType.GetMethod(attr.MethodName, BindingFlags.Static | BindingFlags.Public).Invoke(null, new[] { objectOfDesiredType });

                            return(CreateRef(defType, (IDef)def));
                        }
                    }
                }
            }
            else if (tokenType == JsonToken.StartObject)
            {
                //this is either a template or a def
                //does it make sense to write a template inside a file?
                //Well, in principle, why not?
                if (context.IsProtoChildFile)
                {
                    context.ProtoStack.Peek().Embedded = true;
                }
                var obj = serializer.Deserialize(reader, defType);
                return(CreateRef(defType, (IDef)obj));
            }

            if (tokenType == JsonToken.Boolean || tokenType == JsonToken.Float || tokenType == JsonToken.Integer || tokenType == JsonToken.String)
            {
                var attr = defType.GetCustomAttribute <CanBeCreatedFromAliasedPrimitiveAttribute>(inherit: true);
                if (attr != null)
                {
                    var objectOfDesiredType = PrimitiveTypesConverter.Convert(readerValue, attr.PrimitiveType);
                    var def = defType.GetMethod(attr.MethodName, BindingFlags.Static | BindingFlags.Public).Invoke(null, new[] { objectOfDesiredType });
                    return(CreateRef(defType, (IDef)def));
                }
            }
            //todo make proper line address
            throw new JsonException($"Reference to definition is not a string or object {lineInfo.LineNumber} {lineInfo.LinePosition} {context.RootAddress} - is {tokenType} {readerValue}");
        }
Esempio n. 8
0
 public void SetInternalRes(string id, IDef value)
 {
     LoadingFrames.Peek().Resources.Add(id, value);
 }
Esempio n. 9
0
        //$type
        //$id
        //$vars
        //$overrideVars
        //$proto
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            ClearComments(reader);
            var context  = (LoadingContext)serializer.Context.Context;
            var Context  = context;
            var lineInfo = ((JsonTextReader)reader);

            if (reader.TokenType != JsonToken.StartObject)
            {
                throw new Exception($"Expecting StarObject token at {Context.RootAddress}:{lineInfo.LineNumber}:{lineInfo.LinePosition}, possibly ResourceRef<> wrap is forgotten");
            }
            bool hasId           = false;
            bool hasProto        = false;
            bool hasOverrideVars = false;
            bool hasVars         = false;
            var  startPath       = (string)reader.Path;
            int  startDepth      = reader.Depth;

            ClearComments(reader);
            //skip "$type" propertyname
            reader.Read();
            ClearComments(reader);
            if ((string)reader.Value != "$type")
            {
                throw new Exception($"$type is not first at {lineInfo.LineNumber} {lineInfo.LinePosition} {Context.RootAddress} - val is {reader.Value} {reader.TokenType}");
            }
            reader.Read();
            var specificTypeName = (string)reader.Value;

            reader.Read();

            ClearComments(reader);
            Type specificType = null;

            try
            {
                specificType = serializer.SerializationBinder.BindToType("", specificTypeName);
            }
            catch (Exception e)
            {
                throw new JsonException($"Error reading type {specificTypeName} at {lineInfo.LineNumber} {lineInfo.LinePosition} {Context.RootAddress}", e);
            }


            string id = null;

            if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "$id")
            {
                reader.Read();
                id = (string)reader.Value;
                reader.Read();
                if (id != null)
                {
                    hasId = true;
                }
            }
            ClearComments(reader);
            IDef defInstance = null;
            bool isProto     = false;

            if (reader.TokenType == JsonToken.PropertyName)
            {
                if ((string)reader.Value == "$vars")
                {
                    bool can = false;
                    if (Context.ProtoStack.Count > 0)
                    {
                        can = Context.ProtoStack.Peek().CanRegisterDefInstance;
                        Context.ProtoStack.Peek().CanRegisterDefInstance = false;
                    }

                    hasVars = true;
                    ClearComments(reader);
                    //skip propName
                    reader.Read();
                    //skip startobject
                    reader.Read();
                    while (reader.TokenType != JsonToken.EndObject)
                    {
                        ClearComments(reader);
                        var varName = (string)reader.Value;
                        //skip to content
                        reader.Read();
                        context.PushSubObject();
                        var temVarObj = serializer.Deserialize(reader, typeof(TemplateVariable));
                        //here I'm at the last token of prev object
                        reader.Read();
                        Context.PopSubObject();
                        var temVar = (TemplateVariable)temVarObj;
                        temVar.VariableId = new DefIDFull(Context.RootAddress, lineInfo.LineNumber, lineInfo.LinePosition);
                        if (temVar == null)
                        {
                            throw new JsonException($"Error reading template var {varName} at {lineInfo.LineNumber} {lineInfo.LinePosition} {Context.RootAddress}");
                        }
                        Context.SetVar(varName, temVar);
                    }
                    //skip $vars endObj
                    reader.Read();
                    if (Context.ProtoStack.Count > 0)
                    {
                        Context.ProtoStack.Peek().CanRegisterDefInstance = can;
                    }
                }
                ClearComments(reader);
                if ((string)reader.Value == "$overrideVars" || (string)reader.Value == "$proto")
                {
                    bool can = false;
                    if (Context.ProtoStack.Count > 0)
                    {
                        can = Context.ProtoStack.Peek().CanRegisterDefInstance;
                        Context.ProtoStack.Peek().CanRegisterDefInstance = false;
                    }

                    isProto = true;
                    //here I read "$proto" and "$overrideVars"

                    //load from current context (say if a var points to previously set var)
                    Dictionary <string, KeyValuePair <TemplateVariable, IJsonLineInfo> > vars = new Dictionary <string, KeyValuePair <TemplateVariable, IJsonLineInfo> >();
                    if ((string)reader.Value == "$overrideVars")
                    {
                        hasOverrideVars = true;
                        reader.Read(); //skip propName
                        var startOverrideDepthRead = reader.Depth;
                        reader.Read(); //skip start object
                        while (reader.TokenType != JsonToken.EndObject)
                        {
                            ClearComments(reader);
                            var    varLineInfo     = (JsonTextReader)reader;
                            object value           = null;
                            Type   varTypeIfHasOne = null;
                            Context.PushSubObject();
                            if (reader.TokenType != JsonToken.PropertyName)
                            {
                                throw new Exception("Override var does not start with a property name");
                            }
                            var varNameValue = (string)reader.Value;
                            reader.Read(); // value token (start obj, string or whatever)
                            if (reader.TokenType == JsonToken.String)
                            {
                                var refValue = ((string)reader.Value);
                                if (refValue.StartsWith("@"))
                                {
                                    value = Context.GetVar(refValue.Substring(1), out varTypeIfHasOne);
                                }
                                else if (refValue.StartsWith("/") || refValue.StartsWith("./") || refValue.StartsWith("$"))
                                {
                                    value = serializer.Deserialize(reader, typeof(DefRef <BaseDef>));
                                }
                                else
                                {
                                    value = serializer.Deserialize(reader);
                                }
                            }
                            else
                            {
                                value = serializer.Deserialize(reader);
                            }
                            //here I'm at the last token of override var
                            reader.Read();
                            Context.PopSubObject();
                            vars.Add(varNameValue, new KeyValuePair <TemplateVariable, IJsonLineInfo>(new TemplateVariable()
                            {
                                Type = varTypeIfHasOne, Value = value
                            }, new LineInfo()
                            {
                                Row = varLineInfo.LineNumber, Col = varLineInfo.LinePosition
                            }));
                            ClearComments(reader);
                        }
                        var endOverrideDepthRead = reader.Depth;
                        if (startOverrideDepthRead != endOverrideDepthRead)
                        {
                            throw new Exception($"Depth in override is wrong {startDepth} {endOverrideDepthRead}");
                        }
                        //Skipping end object
                        reader.Read();



                        Context.PushProto(true, new DefIDFull(Context.RootAddress));
                        foreach (var variable in vars)
                        {
                            var value  = variable.Value.Key;
                            var setVar = value.Value;
                            var type   = value.Value?.GetType();
                            if (type == null)
                            {
                                type = value.Type;
                            }
                            if (type != null)
                            {
                                if (typeof(IDef).IsAssignableFrom(type))
                                {
                                    setVar = DefReferenceConverter.CreateRef(type, (IDef)value.Value);
                                    if (setVar != null)
                                    {
                                        type = setVar.GetType();
                                    }
                                }
                            }
                            Context.SetVar(variable.Key, new TemplateVariable()
                            {
                                Value = setVar, Type = type, VariableId = new DefIDFull(Context.RootAddress, variable.Value.Value.LineNumber, variable.Value.Value.LinePosition)
                            });
                        }
                    }
                    else
                    {
                        Context.PushProto(true, new DefIDFull(Context.RootAddress));//Here I could've missed something
                    }
                    while (reader.TokenType == JsonToken.Comment)
                    {
                        reader.Read();
                    }
                    while (reader.TokenType != JsonToken.PropertyName)
                    {
                        reader.Read();
                    }
                    //Skipping $proto
                    if ((string)reader.Value != "$proto")
                    {
                        throw new Exception($"No $proto at {lineInfo.LineNumber} {lineInfo.LinePosition} {Context.RootAddress} - is {reader.Value} {reader.TokenType}");
                    }
                    hasProto = true;
                    reader.Read();
                    Context.PushSubObject();
                    bool setProtoStart = false;
                    if (setProtoStart = !Context.LoadingFrames.Peek().ProtoStart.HasValue)
                    {
                        Context.LoadingFrames.Peek().ProtoStart = new DefIDFull(Context.RootAddress, lineInfo.LineNumber, lineInfo.LinePosition);
                    }
                    var serObj = serializer.Deserialize(reader, (typeof(DefRef <>).MakeGenericType(specificType)));
                    if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.EndObject)
                    {
                        reader.Read();
                    }
                    if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "$overrideVars")
                    {
                        throw new Exception($"$proto and $overrideVars are in a wrong order. Should be $overrideVars and then $proto at {lineInfo.LineNumber} {lineInfo.LinePosition} {Context.RootAddress}");
                    }
                    var rRef = (IRefBase)serObj;
                    defInstance = rRef.DefBase;
                    if (setProtoStart)
                    {
                        Context.LoadingFrames.Peek().ProtoStart = null;
                    }
                    Context.PopSubObject();
                    Context.PopProto();
                    if (defInstance.GetType() != specificType)
                    {
                        throw new JsonException($"Prototype and child resources mismatch {defInstance.GetType().Name} {specificTypeName} at {lineInfo.LineNumber} {lineInfo.LinePosition} {Context.RootAddress}");
                    }

                    if (Context.ProtoStack.Count > 0)
                    {
                        Context.ProtoStack.Peek().CanRegisterDefInstance = can;
                    }
                }
            }

            if (!isProto)
            {
                defInstance = (IDef)Activator.CreateInstance(specificType);
                if (Context.IsProto && Context.ProtoStack.Peek().ProtoObject == null && Context.ProtoStack.Peek().CanRegisterDefInstance)
                {
                    Context.ProtoStack.Peek().ProtoObject = defInstance;
                }
            }

            if (id != null)
            {
                Context.SetInternalRes(id, defInstance);
            }
            var addr = Context.IsRootObject ? new DefIDFull(Context.RootAddress) : new DefIDFull(Context.RootAddress, lineInfo.LineNumber, lineInfo.LinePosition);

            if (!Context.IsProto)
            {
                ((IDef)defInstance).Address = addr;
                loadedResources.RegisterObject(addr, (BaseDef)defInstance);
            }
            else if (Context.ProtoStack.Peek().ProtoObject != defInstance)
            {
                var addrId = new DefIDFull(Context.ProtoRootAdress, lineInfo.LineNumber, lineInfo.LinePosition, Context.ProtoIndex = Context.ProtoIndex + 1);
                ((IDef)defInstance).Address = addrId;
                loadedResources.RegisterObject(addrId, (BaseDef)defInstance);
            }
            Context.PushSubObject();
            var props = ((JsonObjectContract)serializer.ContractResolver.ResolveContract(defInstance.GetType())).Properties;

            //here I'm at a property, which is the first actual property of an object
            ClearComments(reader);
            while (reader.TokenType != JsonToken.EndObject)
            {
                ClearComments(reader);
                if (((string)reader.Value) == null)
                {
                    Logger.Error($"Not Correct Field ({reader.Value.ToString()}) in Jdb file ({reader.Path}). Please fix it!");
                }

                if (props.Contains((string)reader.Value))
                {
                    var prop = props[(string)reader.Value];
                    reader.Read(); //here we are reading value
                    //bool isObj = reader.TokenType == JsonToken.StartObject;
                    var obj = serializer.Deserialize(reader, prop.PropertyType);
                    prop.ValueProvider.SetValue(defInstance, obj);
                    //here we should be at the last token of previous deserializer
                    reader.Read();
                    ClearComments(reader);
                }
                else
                {
                    if ((string)reader.Value == "$id")
                    {
                        throw new Exception($"Id is in wrong place {startPath} {Context.RootAddress}");
                    }
                    reader.Skip();
                    reader.Read();
                }
            }
            int endDepth = reader.Depth;

            if (startDepth != endDepth)
            {
                throw new Exception($"Depth is different {specificTypeName} {startPath} {startDepth} {endDepth} hasId {hasId} hasProto {hasProto} hasOverride {hasOverrideVars} hasVars {hasVars}");
            }
            Context.PopSubObject();
            return(defInstance);
        }