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); }
public static Type GetTypeFromDef(IDef def) { if (def == null) { return(null); } return(_defToInstanceType[def.GetType()]); }
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); }
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); }
public bool Equals(IDef <string> def) => def.Id.Equals(Id);
public DefIDFull GetID(IDef res) => LoadedResources.GetID(res);
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}"); }
public void SetInternalRes(string id, IDef value) { LoadingFrames.Peek().Resources.Add(id, value); }
//$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); }