public static bool LoadLayout(string mapXml, string sceneName, TeamSetting gameMode, int players) { System.IO.File.WriteAllText(logName, ""); // Loading map layout from XML try { XmlTextReader xmlDokmapReader = new XmlTextReader(new System.IO.StringReader(mapXml)); while (xmlDokmapReader.Read()) { if (xmlDokmapReader.NodeType == XmlNodeType.Element) { switch (xmlDokmapReader.Name) { default: System.IO.File.AppendAllText(logName, string.Format("[GE mod] WARNING: Unknown tag '{0}'" + Environment.NewLine, xmlDokmapReader.Name)); Debug.LogWarning(string.Format("[GE mod] WARNING: Unknown tag '{0}'", xmlDokmapReader.Name)); break; case "meta": case "dokmap": break; case "layout": if ((TeamSetting)Enum.Parse(typeof(TeamSetting), xmlDokmapReader.GetAttribute("mode")) == gameMode && (Regex.Replace(xmlDokmapReader.GetAttribute("map"), @"\s+", "").Contains(sceneName) || Regex.Replace(xmlDokmapReader.GetAttribute("map"), @"\s+", "").Contains("*")) && xmlDokmapReader.GetAttribute("players").Contains(players.ToString()[0])) { XmlReader xmlLayoutReader = xmlDokmapReader.ReadSubtree(); while (xmlLayoutReader.Read()) { if (xmlLayoutReader.NodeType == XmlNodeType.Element) { switch (xmlLayoutReader.Name) { // Unimplemented but valid elements case "layout": case "resources": case "artifacts": case "ezs": case "spawns": case "units": case "colliders": case "wrecks": break; case "resource": // collectors is an optional attribute int collectors = 2; try { collectors = int.Parse(xmlLayoutReader.GetAttribute("collectors")); } catch {} resources.Add(new MapResourceData { position = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("x"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("y")))), type = (xmlLayoutReader.GetAttribute("type") == "ru") ? 1 : 0, amount = int.Parse(xmlLayoutReader.GetAttribute("amount")), collectors = collectors, }); break; case "wreck": bool blockLof = false; try { blockLof = Boolean.Parse(xmlLayoutReader.GetAttribute("blocklof")); } catch {} MapWreckData wreck = new MapWreckData { position = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("x"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("y")))), angle = float.Parse(xmlLayoutReader.GetAttribute("angle")), resources = new List <MapResourceData>(), blockLof = blockLof, }; // Read child resources XmlReader xmlLayoutReaderWreck = xmlLayoutReader.ReadSubtree(); while (xmlLayoutReaderWreck.Read()) { // collectors is an optional attribute if (xmlLayoutReaderWreck.NodeType == XmlNodeType.Element && xmlLayoutReaderWreck.Name == "resource") { collectors = 2; try { collectors = int.Parse(xmlLayoutReaderWreck.GetAttribute("collectors")); } catch {} wreck.resources.Add(new MapResourceData { position = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReaderWreck.GetAttribute("x"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReaderWreck.GetAttribute("y")))), type = (xmlLayoutReader.GetAttribute("type") == "ru") ? 1 : 0, amount = int.Parse(xmlLayoutReaderWreck.GetAttribute("amount")), collectors = collectors, }); } } wrecks.Add(wreck); break; case "artifact": artifacts.Add(new MapArtifactData { entity = Entity.None, position = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("x"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("y")))), }); break; case "ez": ezs.Add(new MapEzData { team = int.Parse(xmlLayoutReader.GetAttribute("team")), position = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("x"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("y")))), radius = float.Parse(xmlLayoutReader.GetAttribute("radius")), }); break; case "spawn": // Try to get optional index int spawnIndex = 0; try { spawnIndex = int.Parse(xmlLayoutReader.GetAttribute("index")); } catch {} // Try to get optional camera angle float cameraAngle = 0; try { cameraAngle = float.Parse(xmlLayoutReader.GetAttribute("camera")); } catch {} // Try to get optional fleet toggle bool fleet = true; try { fleet = Boolean.Parse(xmlLayoutReader.GetAttribute("fleet")); } catch {} spawns.Add(new MapSpawnData { team = int.Parse(xmlLayoutReader.GetAttribute("team")), index = spawnIndex, position = new Vector3(float.Parse(xmlLayoutReader.GetAttribute("x")), 0.0f, float.Parse(xmlLayoutReader.GetAttribute("y"))), angle = float.Parse(xmlLayoutReader.GetAttribute("angle")), cameraAngle = cameraAngle, fleet = fleet, }); break; case "unit": // Try to get optional index int unitIndex = 0; try { unitIndex = int.Parse(xmlLayoutReader.GetAttribute("index")); } catch {} units.Add(new MapUnitData { team = int.Parse(xmlLayoutReader.GetAttribute("team")), index = unitIndex, type = xmlLayoutReader.GetAttribute("type"), position = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("x"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("y")))), orientation = Orientation2.FromDirection(Vector2r.Rotate(new Vector2r(Fixed64.FromConstFloat(0.0f), Fixed64.FromConstFloat(1.0f)), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("angle")) / 180.0f * -3.14159f))), }); break; case "heat": heatPoints = int.Parse(xmlLayoutReader.ReadInnerXml()); break; case "bounds": overrideBounds = true; boundsMax = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("right"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("top")))); boundsMin = new Vector2r(Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("left"))), Fixed64.FromConstFloat(float.Parse(xmlLayoutReader.GetAttribute("bottom")))); break; case "blocker": // Parse vertices List <Vector2r> vertices = new List <Vector2r>(); foreach (string vert in xmlLayoutReader.GetAttribute("verts").Split(';')) { float x = float.Parse(vert.Split(',')[0]); float z = float.Parse(vert.Split(',')[1]); vertices.Add(new Vector2r(Fixed64.FromConstFloat(x), Fixed64.FromConstFloat(z))); } ConvexPolygon collider = ConvexPolygon.FromPointCloud(vertices); UnitClass mask = (UnitClass)Enum.Parse(typeof(UnitClass), xmlLayoutReader.GetAttribute("class")); collider.SetLayerFlag((uint)mask); bool blockAllHeights = true; try { blockAllHeights = Boolean.Parse(xmlLayoutReader.GetAttribute("blockallheights")); } catch { blockAllHeights = Boolean.Parse(xmlLayoutReader.GetAttribute("blocklof")); } colliders.Add(new MapColliderData { collider = collider, mask = mask, blockLof = Boolean.Parse(xmlLayoutReader.GetAttribute("blocklof")), blockAllHeights = blockAllHeights, }); break; case "blockers": try { DisableCarrierNavs = !Boolean.Parse(xmlLayoutReader.GetAttribute("carrier")); } catch {} try { DisableAllBlockers = !Boolean.Parse(xmlLayoutReader.GetAttribute("existing")); } catch {} break; default: System.IO.File.AppendAllText(logName, string.Format("[GE mod] WARNING: Unknown tag '{0}'" + Environment.NewLine, xmlLayoutReader.Name)); Debug.LogWarning(string.Format("[GE mod] WARNING: Unknown tag '{0}'", xmlLayoutReader.Name)); break; } } } return(true); } break; } } } return(false); } catch (Exception e) { System.IO.File.AppendAllText(logName, string.Format("[GE mod] ERROR: parsing layout: {0}" + Environment.NewLine, e)); Debug.LogWarning(string.Format("[GE mod] ERROR: parsing layout: {0}", e)); System.Diagnostics.Process.Start(logName); ResetLayout(); MapXml = ""; LayoutName = ""; return(false); } }