public Entity SpawnEntity(EntityBlueprint blueprint, Sector.LevelEntity data) { GameObject gObj = new GameObject(data.name); string json = null; switch (blueprint.intendedType) { case EntityBlueprint.IntendedType.ShellCore: { ShellCore shellcore = gObj.AddComponent <ShellCore>(); try { // Check if data has blueprint JSON, if it does override the current blueprint // this now specifies the path to the JSON file instead of being the JSON itself json = data.blueprintJSON; if (json != null && json != "") { blueprint = ScriptableObject.CreateInstance <EntityBlueprint>(); // try parsing directly, if that fails try fetching the entity file try { JsonUtility.FromJsonOverwrite(json, blueprint); } catch { JsonUtility.FromJsonOverwrite(System.IO.File.ReadAllText (resourcePath + "\\Entities\\" + json + ".json"), blueprint); } //Debug.Log(data.name); blueprint.entityName = data.name; } else { shellcore.entityName = blueprint.entityName = data.name; } if (current.type == Sector.SectorType.BattleZone) { // add core arrow if (MinimapArrowScript.instance && !(shellcore is PlayerCore)) { shellcore.faction = data.faction; MinimapArrowScript.instance.AddCoreArrow(shellcore); } // set the carrier of the shellcore to the associated faction's carrier if (carriers.ContainsKey(data.faction)) { shellcore.SetCarrier(carriers[data.faction]); } battleZone.AddTarget(shellcore); } } catch (System.Exception e) { Debug.Log(e.Message); //blueprint = obj as EntityBlueprint; } shellcore.sectorMngr = this; break; } case EntityBlueprint.IntendedType.PlayerCore: { if (player == null) { player = gObj.AddComponent <PlayerCore>(); player.sectorMngr = this; } else { Destroy(gObj); return(null); } break; } case EntityBlueprint.IntendedType.Turret: { gObj.AddComponent <Turret>(); break; } case EntityBlueprint.IntendedType.Tank: { gObj.AddComponent <Tank>(); break; } case EntityBlueprint.IntendedType.Bunker: { json = data.blueprintJSON; if (json != null && json != "") { var dialogueRef = blueprint.dialogue; blueprint = ScriptableObject.CreateInstance <EntityBlueprint>(); // try parsing directly, if that fails try fetching the entity file try { JsonUtility.FromJsonOverwrite(json, blueprint); } catch { JsonUtility.FromJsonOverwrite(System.IO.File.ReadAllText (resourcePath + "\\Entities\\" + json + ".json"), blueprint); } blueprint.dialogue = dialogueRef; } blueprint.entityName = data.name; Bunker bunker = gObj.AddComponent <Bunker>(); stations.Add(bunker); bunker.vendingBlueprint = blueprint.dialogue != null ? blueprint.dialogue.vendingBlueprint : ResourceManager.GetAsset <VendingBlueprint>(data.vendingID); break; } case EntityBlueprint.IntendedType.Outpost: { json = data.blueprintJSON; if (json != null && json != "") { var dialogueRef = blueprint.dialogue; blueprint = ScriptableObject.CreateInstance <EntityBlueprint>(); // try parsing directly, if that fails try fetching the entity file try { JsonUtility.FromJsonOverwrite(json, blueprint); } catch { JsonUtility.FromJsonOverwrite(System.IO.File.ReadAllText (resourcePath + "\\Entities\\" + json + ".json"), blueprint); } blueprint.dialogue = dialogueRef; } blueprint.entityName = data.name; Outpost outpost = gObj.AddComponent <Outpost>(); stations.Add(outpost); outpost.vendingBlueprint = blueprint.dialogue != null ? blueprint.dialogue.vendingBlueprint : ResourceManager.GetAsset <VendingBlueprint>(data.vendingID); break; } case EntityBlueprint.IntendedType.Tower: { break; } case EntityBlueprint.IntendedType.Drone: { Drone drone = gObj.AddComponent <Drone>(); //drone.path = ResourceManager.GetAsset<Path>(data.pathID); break; } case EntityBlueprint.IntendedType.AirCarrier: json = data.blueprintJSON; if (json != null && json != "") { blueprint = ScriptableObject.CreateInstance <EntityBlueprint>(); // try parsing directly, if that fails try fetching the entity file try { JsonUtility.FromJsonOverwrite(json, blueprint); } catch { JsonUtility.FromJsonOverwrite(System.IO.File.ReadAllText (resourcePath + "\\Entities\\" + json + ".json"), blueprint); } } blueprint.entityName = data.name; AirCarrier carrier = gObj.AddComponent <AirCarrier>(); if (!carriers.ContainsKey(data.faction)) { carriers.Add(data.faction, carrier); } carrier.sectorMngr = this; break; case EntityBlueprint.IntendedType.GroundCarrier: json = data.blueprintJSON; if (json != null && json != "") { blueprint = ScriptableObject.CreateInstance <EntityBlueprint>(); // try parsing directly, if that fails try fetching the entity file try { JsonUtility.FromJsonOverwrite(json, blueprint); } catch { JsonUtility.FromJsonOverwrite(System.IO.File.ReadAllText (resourcePath + "\\Entities\\" + json + ".json"), blueprint); } } blueprint.entityName = data.name; GroundCarrier gcarrier = gObj.AddComponent <GroundCarrier>(); if (!carriers.ContainsKey(data.faction)) { carriers.Add(data.faction, gcarrier); } gcarrier.sectorMngr = this; break; case EntityBlueprint.IntendedType.Yard: Yard yard = gObj.AddComponent <Yard>(); yard.mode = BuilderMode.Yard; break; case EntityBlueprint.IntendedType.WeaponStation: gObj.AddComponent <WeaponStation>(); break; case EntityBlueprint.IntendedType.CoreUpgrader: gObj.AddComponent <CoreUpgrader>(); break; case EntityBlueprint.IntendedType.Trader: Yard trade = gObj.AddComponent <Yard>(); trade.mode = BuilderMode.Trader; try { bool ok = true; if (blueprint.dialogue == null) { ok = false; } if (blueprint.dialogue.traderInventory == null) { ok = false; } if (data.blueprintJSON == null || data.blueprintJSON == "") { ok = false; } if (ok) { ShipBuilder.TraderInventory inventory = JsonUtility.FromJson <ShipBuilder.TraderInventory>(data.blueprintJSON); if (inventory.parts != null) { blueprint.dialogue.traderInventory = inventory.parts; } } else { blueprint.dialogue.traderInventory = new List <EntityBlueprint.PartInfo>(); } } catch (System.Exception e) { Debug.LogWarning(e); blueprint.dialogue.traderInventory = new List <EntityBlueprint.PartInfo>(); } break; case EntityBlueprint.IntendedType.DroneWorkshop: Yard workshop = gObj.AddComponent <Yard>(); workshop.mode = BuilderMode.Workshop; break; default: break; } Entity entity = gObj.GetComponent <Entity>(); // TODO: These lines should perhaps be moved somewhere inside Entity itself, they need to run before even Awake is called if (!AIData.entities.Contains(entity)) { AIData.entities.Add(entity); } entity.sectorMngr = this; entity.faction = data.faction; entity.spawnPoint = entity.transform.position = data.position; entity.blueprint = blueprint; if (entity as AirCraft && data.patrolPath != null && data.patrolPath.waypoints != null && data.patrolPath.waypoints.Count > 0) { // patrolling (entity as AirCraft).GetAI().setPath(data.patrolPath, null, true); } if (data.ID == "" || data.ID == null || (objects.ContainsKey(data.ID) && !objects.ContainsValue(gObj))) { data.ID = objects.Count.ToString(); } entity.ID = data.ID; if (!objects.ContainsKey(data.ID)) { objects.Add(data.ID, gObj); } return(entity); }
IEnumerator WriteWorldCo(string path) { Debug.Log("Writing world..."); // Folder paths var canvasPlaceholderPath = System.IO.Path.Combine(Application.streamingAssetsPath, "CanvasPlaceholder"); var entityPlaceholderPath = System.IO.Path.Combine(Application.streamingAssetsPath, "EntityPlaceholder"); var wavePlaceholderPath = System.IO.Path.Combine(Application.streamingAssetsPath, "WavePlaceholder"); var factionPlaceholderPath = System.IO.Path.Combine(Application.streamingAssetsPath, "FactionPlaceholder"); var resourcePlaceholderPath = System.IO.Path.Combine(Application.streamingAssetsPath, "ResourcePlaceholder"); // Reinitialize node editor NodeEditor.ReInit(false); saveState = 1; yield return(null); sectors = new List <Sector>(); var items = cursor.placedItems; var wrappers = cursor.sectors; foreach (var wrapper in wrappers) { sectors.Add(wrapper.sector); } int minX = int.MaxValue; int maxY = int.MinValue; // Get the world bounds foreach (var sector in sectors) { if (sector.bounds.x < minX) { minX = sector.bounds.x; } if (sector.bounds.y > maxY) { maxY = sector.bounds.y; } } // ensure spawn point in some sector if (sectors.TrueForAll(sector => !sector.bounds.contains(cursor.spawnPoint.position))) { Debug.LogError("Spawn point not in sector bounds. Abort."); yield break; } // set up items and platforms int ID = 0; Dictionary <Sector, List <Sector.LevelEntity> > sectEnts = new Dictionary <Sector, List <Sector.LevelEntity> >(); Dictionary <Sector, List <string> > sectTargetIDS = new Dictionary <Sector, List <string> >(); foreach (var sector in sectors) { sectEnts.Add(sector, new List <Sector.LevelEntity>()); sectTargetIDS.Add(sector, new List <string>()); sector.tiles = new List <GroundPlatform.Tile>(); } // Add background spawns to part index partData.Clear(); foreach (var sector in sectors) { if (sector.backgroundSpawns != null) { foreach (var spawn in sector.backgroundSpawns) { AttemptAddShellCoreParts(spawn.entity, sector.sectorName, path); } } } Dictionary <string, string> itemSectorsByID = new Dictionary <string, string>(); foreach (var item in items) { Sector container = GetSurroundingSector(item.pos, item.dimension); if (container == null) { savingLevelScreen.SetActive(false); saveState = 3; Debug.LogError("No container for item. Abort."); yield break; } switch (item.type) { case ItemType.Platform: var index = GetPlatformIndices(container, item.pos); container.tiles.Add(new GroundPlatform.Tile() { pos = new Vector2Int(index.Item2, index.Item1), type = (byte)item.placeablesIndex, rotation = (byte)(((int)item.obj.transform.rotation.eulerAngles.z / 90) % 4) }); break; case ItemType.Other: case ItemType.Decoration: case ItemType.DecorationWithMetadata: case ItemType.Flag: Sector.LevelEntity ent = new Sector.LevelEntity(); if (cursor.characters.TrueForAll((WorldData.CharacterData x) => { return(x.ID != item.ID); })) { // Debug.Log(item.ID + " is not a character. " + ID); if (item.type == ItemType.DecorationWithMetadata) { int parsedId; if (item.assetID == "shard_rock" && int.TryParse(item.ID, out parsedId)) { Debug.LogError($"Shard in sector {container.sectorName} has a numeric ID. Abort."); yield break; } ent.blueprintJSON = item.shellcoreJSON; } int test; if (string.IsNullOrEmpty(item.ID) || int.TryParse(item.ID, out test)) { ent.ID = (ID++).ToString(); } else { ent.ID = item.ID; if (itemSectorsByID.ContainsKey(ent.ID)) { savingLevelScreen.SetActive(false); saveState = 4; Debug.LogError($"Two items in sectors {container.sectorName} and {itemSectorsByID[ent.ID]} were issued the same custom ID ({ent.ID}). Abort."); yield break; } else { itemSectorsByID.Add(ent.ID, container.sectorName); } } // Debug.Log(container.sectorName + " " + ent.ID); } else { // TODO: adjust faction Debug.Log("Character found. Adjusting ID and name"); ent.ID = item.ID; } // you can choose to give any object a custom name if (!string.IsNullOrEmpty(item.name)) { ent.name = item.name; } else { ent.name = item.obj.name; } ent.faction = item.faction; ent.position = item.pos; ent.assetID = item.assetID; ent.vendingID = item.vendingID; ent.patrolPath = item.patrolPath; if ((item.isTarget && container.type != Sector.SectorType.SiegeZone) || (container.type == Sector.SectorType.SiegeZone && item.assetID == "outpost_blueprint" && item.faction == 0) || (container.type == Sector.SectorType.SiegeZone && item.assetID == "bunker_blueprint" && item.faction == 0)) { sectTargetIDS[container].Add(ent.ID); } var charExists = cursor.characters.Exists(ch => ch.ID == ent.ID); if (ent.assetID == "shellcore_blueprint" || charExists) { if (container.type != Sector.SectorType.SiegeZone && !sectTargetIDS[container].Contains(ent.ID)) { sectTargetIDS[container].Add(ent.ID); } ent.blueprintJSON = item.shellcoreJSON; if (!charExists) { AttemptAddShellCoreParts(ent, container.sectorName, path); } } else if (ent.assetID == "trader_blueprint") { ent.blueprintJSON = item.shellcoreJSON; // Attempt to add trader parts into index. if (string.IsNullOrEmpty(ent.blueprintJSON)) { var dialogueDataPath = System.IO.Path.Combine(canvasPlaceholderPath, ent.ID, ".dialoguedata"); if (System.IO.File.Exists(dialogueDataPath)) { var XMLImport = new XMLImportExport(); var canvas = XMLImport.Import(dialogueDataPath) as DialogueCanvas; foreach (var node in canvas.nodes) { if (node is EndDialogue endDialogue && endDialogue.openTrader) { ShipBuilder.TraderInventory traderInventory = JsonUtility.FromJson <ShipBuilder.TraderInventory>(endDialogue.traderJSON); AttemptAddPartArray(traderInventory.parts, container.sectorName); } } } else { ent.blueprintJSON = JsonUtility.ToJson(new ShipBuilder.TraderInventory()); // Maybe make this error message more descriptive. Debug.LogWarning($"Trader has neither default trader JSON nor an associated dialogue file named '{ent.ID}.dialoguedata'. Replacing with empty trader inventory."); } } else { ShipBuilder.TraderInventory traderInventory = JsonUtility.FromJson <ShipBuilder.TraderInventory>(ent.blueprintJSON); AttemptAddPartArray(traderInventory.parts, container.sectorName); } } else if (ent.assetID == "groundcarrier_blueprint" || ent.assetID == "carrier_blueprint" || ent.assetID == "outpost_blueprint" || ent.assetID == "bunker_blueprint" || ent.assetID == "missile_station" || ent.assetID == "air_weapon_station") { ent.blueprintJSON = item.shellcoreJSON; } sectEnts[container].Add(ent); break; default: break; } } if (!System.IO.Directory.Exists(canvasPlaceholderPath)) { System.IO.Directory.CreateDirectory(canvasPlaceholderPath); } // create world data WorldData wdata = ScriptableObject.CreateInstance <WorldData>(); wdata.sectorMappings = new List <WorldData.OffloadMappings>(); wdata.dialogueMappings = new List <WorldData.OffloadMappings>(); // Add reward parts from tasks. if (System.IO.Directory.Exists(canvasPlaceholderPath)) { foreach (var canvasPath in System.IO.Directory.GetFiles(canvasPlaceholderPath)) { var pathWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(canvasPath); var XMLImport = new XMLImportExport(); switch (System.IO.Path.GetExtension(canvasPath)) { case ".taskdata": var questCanvas = XMLImport.Import(canvasPath) as QuestCanvas; string missionName = null; foreach (var node in questCanvas.nodes) { if (node is StartMissionNode startMission) { missionName = startMission.missionName; } } foreach (var node in questCanvas.nodes) { if (node is StartTaskNode startTask && startTask.partReward) { EntityBlueprint.PartInfo part = new EntityBlueprint.PartInfo(); part.partID = startTask.partID; part.abilityID = startTask.partAbilityID; part.tier = startTask.partTier; part.secondaryData = startTask.partSecondaryData; part = PartIndexScript.CullToPartIndexValues(part); AddPart(part, missionName); } } if (missionName != null) { File.Move(canvasPath, System.IO.Path.Combine(System.IO.Path.GetDirectoryName(canvasPath), missionName + ".taskdata")); } break; case ".sectordata": var sectorCanvas = XMLImport.Import(canvasPath) as SectorCanvas; var sectorName = new SectorTraverser(sectorCanvas).findRoot().sectorName; wdata.sectorMappings.Add(new WorldData.OffloadMappings(sectorName, pathWithoutExtension)); //var newPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(canvasPath), sectorName + ".sectordata"); //if (!File.Exists(newPath)) // File.Move(canvasPath, newPath); break; case ".dialoguedata": var dialogueCanvas = XMLImport.Import(canvasPath) as DialogueCanvas; var entityID = new DialogueTraverser(dialogueCanvas).findRoot().EntityID; wdata.dialogueMappings.Add(new WorldData.OffloadMappings(entityID, pathWithoutExtension)); //File.Move(canvasPath, System.IO.Path.Combine(System.IO.Path.GetDirectoryName(canvasPath), entityID + ".dialoguedata")); break; } } } // try to write out resources. Factions are obtained from the FactionManager if (!System.IO.Directory.Exists(factionPlaceholderPath)) { System.IO.Directory.CreateDirectory(factionPlaceholderPath); } var resourceTxtPath = System.IO.Path.Combine(Application.streamingAssetsPath, "ResourceDataPlaceholder.txt"); if (System.IO.File.Exists(resourceTxtPath)) { // first, extract all the lines without the factions. List <string> lines = new List <string>(); using (StreamReader sr = File.OpenText(resourceTxtPath)) { string s; bool onFactions = false; while ((s = sr.ReadLine()) != null) { if (ResourceManager.resourceHeaders.Any(header => s.ToLower().StartsWith(header))) { if (s.ToLower().StartsWith("factions:")) { onFactions = true; } else { onFactions = false; } } if (!onFactions) { lines.Add(s); } } } // we then reconstruct the factions tab with FM data lines.Add("factions:"); foreach (var faction in factionManager.factions) { // avoid default factions if (FactionManager.defaultFactions.Contains(faction)) { continue; } lines.Add($"{faction.factionName}:Factions/{faction.factionName}.json"); } File.WriteAllLines(resourceTxtPath, lines); } // calculate land platform pathfinding directions foreach (var sector in sectors) { if (sector.tiles != null && sector.tiles.Count > 0) { sector.platforms = LandPlatformGenerator.DivideToPlatforms(sector.tiles); List <string> data = new List <string>(); foreach (var plat in sector.platforms) { data.Add(plat.Encode()); } sector.platformData = data.ToArray(); } else { sector.platforms = new GroundPlatform[0]; sector.platformData = new string[0]; } } // write all sectors into a file if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } // Delete all unnecessary files if (System.IO.Directory.Exists(path)) { string[] resPaths = ResourceManager.Instance.GetFileNames(path); for (int i = 0; i < resPaths.Length; i++) { resPaths[i] = resPaths[i].Replace('\\', '/'); Debug.Log("Res path: " + resPaths[i]); } string[] directories = System.IO.Directory.GetDirectories(path); foreach (var dir in directories) { bool del = true; foreach (var f in System.IO.Directory.GetFiles(dir)) { Debug.Log("File in dir: " + System.IO.Path.Combine(dir, f)); if (!resPaths.Contains(System.IO.Path.Combine(dir, f).Replace('\\', '/'))) { System.IO.File.Delete(f); } del = false; } if (del) { System.IO.Directory.Delete(dir); } } string[] files = System.IO.Directory.GetFiles(path); foreach (var file in files) { string f = file.Replace('\\', '/'); if ((!resPaths.Contains(f) && f != System.IO.Path.Combine(path, "ResourceData.txt").Replace('\\', '/')) || legacyFactionFilesToDelete.Contains(file)) { System.IO.File.Delete(file); } } } wdata.initialSpawn = cursor.spawnPoint.position; wdata.defaultCharacters = cursor.characters.ToArray(); wdata.defaultBlueprintJSON = blueprintField.text; wdata.author = authorField.text; wdata.description = descriptionField.text; wdata.partIndexDataArray = partData.ToArray(); string wdjson = JsonUtility.ToJson(wdata); System.IO.File.WriteAllText(System.IO.Path.Combine(path, "world.worlddata"), wdjson); if (File.Exists(System.IO.Path.Combine(path, "ResourceData.txt"))) { File.Delete(System.IO.Path.Combine(path, "ResourceData.txt")); } if (File.Exists(resourceTxtPath)) { File.Copy(resourceTxtPath, System.IO.Path.Combine(path, "ResourceData.txt")); } TryCopy(canvasPlaceholderPath, System.IO.Path.Combine(path, "Canvases")); TryCopy(entityPlaceholderPath, System.IO.Path.Combine(path, "Entities")); TryCopy(wavePlaceholderPath, System.IO.Path.Combine(path, "Waves")); TryCopy(factionPlaceholderPath, System.IO.Path.Combine(path, "Factions")); TryCopy(resourcePlaceholderPath, System.IO.Path.Combine(path, "Resources")); foreach (var sector in sectors) { if (string.IsNullOrEmpty(sector.sectorName)) { sector.sectorName = GetDefaultName(sector, minX, maxY); } if (sector.hasMusic && string.IsNullOrEmpty(sector.musicID)) { sector.musicID = GetDefaultMusic(sector.type); } sector.entities = sectEnts[sector].ToArray(); sector.targets = sectTargetIDS[sector].ToArray(); // sector.backgroundColor = SectorColors.colors[(int)sector.type]; SectorData data = new SectorData(); data.sectorjson = JsonUtility.ToJson(sector); data.platformjson = ""; // For backwards compatibility... string output = JsonUtility.ToJson(data); string sectorPath = System.IO.Path.Combine(path, sector.sectorName + ".json"); System.IO.File.WriteAllText(sectorPath, output); } Debug.Log("JSON written to location: " + path); Debug.Log($"Index size: {partData.Count}"); savingLevelScreen.SetActive(false); saveState = 2; if (OnSectorSaved != null) { OnSectorSaved.Invoke(); } }
IEnumerator WriteWorldCo(string path) { Debug.Log("Writing world..."); // Folder paths var canvasPlaceholderPath = Application.streamingAssetsPath + "\\CanvasPlaceholder"; var entityPlaceholderPath = Application.streamingAssetsPath + "\\EntityPlaceholder"; var wavePlaceholderPath = Application.streamingAssetsPath + "\\WavePlaceholder"; // Reinitialize node editor NodeEditor.ReInit(false); saveState = 1; yield return(null); sectors = new List <Sector>(); var items = cursor.placedItems; var wrappers = cursor.sectors; foreach (var wrapper in wrappers) { sectors.Add(wrapper.sector); } int minX = int.MaxValue; int maxY = int.MinValue; // Get the world bounds foreach (var sector in sectors) { if (sector.bounds.x < minX) { minX = sector.bounds.x; } if (sector.bounds.y > maxY) { maxY = sector.bounds.y; } } // ensure spawn point in some sector if (sectors.TrueForAll(sector => !sector.bounds.contains(cursor.spawnPoint.position))) { Debug.LogError("Spawn point not in sector bounds. Abort."); yield break; } // set up items and platforms int ID = 0; Dictionary <Sector, List <Sector.LevelEntity> > sectEnts = new Dictionary <Sector, List <Sector.LevelEntity> >(); Dictionary <Sector, List <string> > sectTargetIDS = new Dictionary <Sector, List <string> >(); foreach (var sector in sectors) { sectEnts.Add(sector, new List <Sector.LevelEntity>()); sectTargetIDS.Add(sector, new List <string>()); sector.tiles = new List <GroundPlatform.Tile>(); } // Add background spawns to part index partData.Clear(); foreach (var sector in sectors) { if (sector.backgroundSpawns != null) { foreach (var spawn in sector.backgroundSpawns) { AttemptAddShellCoreParts(spawn.entity, sector.sectorName, path); } } } Dictionary <string, string> itemSectorsByID = new Dictionary <string, string>(); foreach (var item in items) { Sector container = GetSurroundingSector(item.pos); if (container == null) { savingLevelScreen.SetActive(false); saveState = 3; Debug.LogError("No container for item. Abort."); yield break; } switch (item.type) { case ItemType.Platform: var index = GetPlatformIndices(container, item.pos); container.tiles.Add(new GroundPlatform.Tile() { pos = new Vector2Int(index.Item2, index.Item1), type = (byte)item.placeablesIndex, rotation = (byte)(((int)item.obj.transform.rotation.eulerAngles.z / 90) % 4), directions = new Dictionary <Vector2Int, byte>() }); break; case ItemType.Other: case ItemType.Decoration: case ItemType.Flag: Sector.LevelEntity ent = new Sector.LevelEntity(); if (cursor.characters.TrueForAll((WorldData.CharacterData x) => { return(x.ID != item.ID); })) { // Debug.Log(item.ID + " is not a character. " + ID); int test; if (item.ID == null || item.ID == "" || int.TryParse(item.ID, out test)) { ent.ID = ID++ + ""; } else { ent.ID = item.ID; if (itemSectorsByID.ContainsKey(ent.ID)) { savingLevelScreen.SetActive(false); saveState = 4; Debug.LogError("Two items in sectors " + container.sectorName + " and " + itemSectorsByID[ent.ID] + " were issued the same custom ID. Abort."); yield break; } else { itemSectorsByID.Add(ent.ID, container.sectorName); } } // Debug.Log(container.sectorName + " " + ent.ID); } else { // TODO: adjust faction Debug.Log("Character found. Adjusting ID and name"); ent.ID = item.ID; } // you can choose to give any object a custom name if (item.name != null && item.name != "") { ent.name = item.name; } else { ent.name = item.obj.name; } ent.faction = item.faction; ent.position = item.pos; ent.assetID = item.assetID; ent.vendingID = item.vendingID; ent.patrolPath = item.patrolPath; if ((item.isTarget && container.type != Sector.SectorType.SiegeZone) || (container.type == Sector.SectorType.SiegeZone && item.assetID == "outpost_blueprint" && item.faction == 0) || (container.type == Sector.SectorType.SiegeZone && item.assetID == "bunker_blueprint" && item.faction == 0)) { sectTargetIDS[container].Add(ent.ID); } var charExists = cursor.characters.Exists(ch => ch.ID == ent.ID); if (ent.assetID == "shellcore_blueprint" || charExists) { if (container.type != Sector.SectorType.SiegeZone && !sectTargetIDS[container].Contains(ent.ID)) { sectTargetIDS[container].Add(ent.ID); } ent.blueprintJSON = item.shellcoreJSON; if (!charExists) { AttemptAddShellCoreParts(ent, container.sectorName, path); } } else if (ent.assetID == "trader_blueprint") { ent.blueprintJSON = item.shellcoreJSON; // Attempt to add trader parts into index. if (ent.blueprintJSON == null || ent.blueprintJSON == "") { var dialogueDataPath = $"{canvasPlaceholderPath}\\{ent.ID}.dialoguedata"; if (System.IO.File.Exists(dialogueDataPath)) { var XMLImport = new XMLImportExport(); var canvas = XMLImport.Import(dialogueDataPath) as DialogueCanvas; foreach (var node in canvas.nodes) { if (node is EndDialogue) { var endDialogue = node as EndDialogue; if (endDialogue.openTrader) { ShipBuilder.TraderInventory traderInventory = JsonUtility.FromJson <ShipBuilder.TraderInventory>(endDialogue.traderJSON); Debug.LogError(container.sectorName + "end dialog"); AttemptAddPartArray(traderInventory.parts, container.sectorName); } } } } else { ent.blueprintJSON = JsonUtility.ToJson(new ShipBuilder.TraderInventory()); // Maybe make this error message more descriptive. Debug.LogWarning($"Trader has neither default trader JSON nor an associated dialogue file named '{ent.ID}.dialoguedata'. Replacing with empty trader inventory."); } } else { ShipBuilder.TraderInventory traderInventory = JsonUtility.FromJson <ShipBuilder.TraderInventory>(ent.blueprintJSON); AttemptAddPartArray(traderInventory.parts, container.sectorName); } } else if (ent.assetID == "groundcarrier_blueprint" || ent.assetID == "carrier_blueprint" || ent.assetID == "outpost_blueprint" || ent.assetID == "bunker_blueprint") { ent.blueprintJSON = item.shellcoreJSON; } sectEnts[container].Add(ent); break; default: break; } } if (!System.IO.Directory.Exists(canvasPlaceholderPath)) { System.IO.Directory.CreateDirectory(canvasPlaceholderPath); } // Add reward parts from tasks. if (System.IO.Directory.Exists(canvasPlaceholderPath)) { foreach (var canvasPath in System.IO.Directory.GetFiles(canvasPlaceholderPath)) { if (System.IO.Path.GetExtension(canvasPath) == ".taskdata") { var XMLImport = new XMLImportExport(); var canvas = XMLImport.Import(canvasPath) as QuestCanvas; string missionName = null; foreach (var node in canvas.nodes) { if (node is StartMissionNode) { var startMission = node as StartMissionNode; missionName = startMission.missionName; } } foreach (var node in canvas.nodes) { if (node is StartTaskNode) { var startTask = node as StartTaskNode; if (startTask.partReward) { EntityBlueprint.PartInfo part = new EntityBlueprint.PartInfo(); part.partID = startTask.partID; part.abilityID = startTask.partAbilityID; part.tier = startTask.partTier; part.secondaryData = startTask.partSecondaryData; part = PartIndexScript.CullToPartIndexValues(part); AddPart(part, missionName); } } } } } } // calculate land platform pathfinding directions foreach (var sector in sectors) { if (sector.tiles != null && sector.tiles.Count > 0) { sector.platforms = LandPlatformGenerator.DivideToPlatforms(sector.tiles); List <string> data = new List <string>(); foreach (var plat in sector.platforms) { plat.GenerateDirections(); data.Add(plat.Encode()); } sector.platformData = data.ToArray(); } else { sector.platforms = new GroundPlatform[0]; sector.platformData = new string[0]; } } // write all sectors into a file if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } // Delete all unnecessary files if (System.IO.Directory.Exists(path)) { string[] resPaths = ResourceManager.Instance.GetFileNames(path); for (int i = 0; i < resPaths.Length; i++) { resPaths[i] = resPaths[i].Replace('\\', '/'); Debug.Log("Res path: " + resPaths[i]); } string[] directories = System.IO.Directory.GetDirectories(path); foreach (var dir in directories) { bool del = true; foreach (var f in System.IO.Directory.GetFiles(dir)) { Debug.Log("File in dir: " + System.IO.Path.Combine(dir, f)); if (!resPaths.Contains(System.IO.Path.Combine(dir, f).Replace('\\', '/'))) { System.IO.File.Delete(f); del = false; } } if (del) { System.IO.Directory.Delete(dir); } } string[] files = System.IO.Directory.GetFiles(path); foreach (var file in files) { string f = file.Replace('\\', '/'); if (!resPaths.Contains(f) && f != System.IO.Path.Combine(path, "ResourceData.txt").Replace('\\', '/')) { System.IO.File.Delete(file); } } } // create world data WorldData wdata = ScriptableObject.CreateInstance <WorldData>(); wdata.initialSpawn = cursor.spawnPoint.position; wdata.defaultCharacters = cursor.characters.ToArray(); wdata.defaultBlueprintJSON = blueprintField.text; wdata.author = authorField.text; wdata.description = descriptionField.text; wdata.partIndexDataArray = partData.ToArray(); string wdjson = JsonUtility.ToJson(wdata); System.IO.File.WriteAllText(path + "\\world.worlddata", wdjson); TryCopy(canvasPlaceholderPath, path + "\\Canvases\\"); TryCopy(entityPlaceholderPath, path + "\\Entities\\"); TryCopy(wavePlaceholderPath, path + "\\Waves\\"); foreach (var sector in sectors) { if (sector.sectorName == null || sector.sectorName == "") { sector.sectorName = GetDefaultName(sector, minX, maxY); } if (sector.hasMusic && (sector.musicID == null || sector.musicID == "")) { sector.musicID = GetDefaultMusic(sector.type); } sector.entities = sectEnts[sector].ToArray(); sector.targets = sectTargetIDS[sector].ToArray(); // sector.backgroundColor = SectorColors.colors[(int)sector.type]; SectorData data = new SectorData(); data.sectorjson = JsonUtility.ToJson(sector); data.platformjson = ""; // For backwards compatibility... string output = JsonUtility.ToJson(data); string sectorPath = path + "\\." + sector.sectorName + ".json"; System.IO.File.WriteAllText(sectorPath, output); } Debug.Log("JSON written to location: " + path); Debug.Log($"Index size: {partData.Count}"); savingLevelScreen.SetActive(false); saveState = 2; if (OnSectorSaved != null) { OnSectorSaved.Invoke(); } }