Esempio n. 1
0
    public void startSectorGraph(string sectorName)
    {
        if (!offloadingSectors.ContainsKey(sectorName))
        {
            return;
        }
        var pathList = offloadingSectors[sectorName];

        offloadingSectors.Remove(sectorName);
        var XMLImport = new XMLImportExport();

        foreach (var path in pathList)
        {
            var canvas = XMLImport.Import(path) as SectorCanvas;
            if (canvas != null)
            {
                var traverser = new SectorTraverser(canvas);
                sectorTraversers.Add(traverser);
                if (traverser != null)
                {
                    var start = traverser.findRoot();
                    traverser.startNode = (LoadSectorNode)start;
                    traverser.StartQuest();
                }
            }
        }
    }
Esempio n. 2
0
    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();
        }
    }