private void AddSchemaType(SchemaType type) { SchemaTypeMap[type.Name] = type; SchemaTypes.Add(type.Name); }
/// <summary> /// Loads a Noita schema file (data/schemas) as an XWitch schema object. /// </summary> /// <param name="reader">Stream reader.</param> /// <param name="id">Optional ID to use for this schema (`"noita"` by default).</param> /// <param name="metaschema">Optional XWitch schema object that defines unknown types used in the schema (will try to get an already registered schema with the ID `ecs` if this isn't passed).</param> public void LoadFromNoitaSchema(StreamReader reader, string id = null, Schema metaschema = null) { if (metaschema == null) { metaschema = Schema.TryGetSchema(DEFAULT_NOITA_METASCHEMA_ID); if (metaschema == null) { throw new Exception($"No metaschema given to LoadNoitaSchema and no schema with the ID 'ecs' registered"); } } if (id == null) { id = "noita"; } ID = id; ResetData(); var doc = new HtmlDocument(); doc.Load(reader); if (doc.DocumentNode.ChildNodes.Count == 0) { return; } var root = doc.DocumentNode.ChildNodes[0]; if (root.NodeType != HtmlNodeType.Element || root.Name != "Schema") { return; } if (TryGetSchema(ID) != null) { throw new Exception($"Schema with ID {ID} is already loaded"); } AddToLibrary(this); for (var i = 0; i < root.ChildNodes.Count; i++) { var child = root.ChildNodes[i]; if (child.NodeType != HtmlNodeType.Element) { continue; } var type = new SchemaObjectType(); type.ArrayType = false; type.FieldNames = new List <string>(); type.FieldTypes = new Dictionary <string, SchemaType>(); type.Name = child.GetAttributeValue("component_name", null); AddSchemaType(type); for (var j = 0; j < child.ChildNodes.Count; j++) { var varchild = child.ChildNodes[j]; if (varchild.NodeType != HtmlNodeType.Element) { continue; } var name = varchild.GetAttributeValue("name", null); var size = int.Parse(varchild.GetAttributeValue("size", null)); SchemaType field_type = null; var override_type = metaschema.GetSchemaOverride(type.Name, name); if (override_type == null) { var ceng_type_name = varchild.GetAttributeValue("type", null).Trim(); field_type = metaschema.GetSchemaType(ceng_type_name); if (field_type.ExpectedSize != size) { throw new Exception($"Type size mismatch: metaschema-defined type '{field_type.Name}' expects size to be {field_type.ExpectedSize}, but actual size of field '{name}' in component '{type.Name}' is {size}"); } } else { field_type = override_type; } type.FieldNames.Add(name); type.FieldTypes[name] = field_type; } } }