Beispiel #1
0
        public RecipeUnlockReward(string itemName, string rewardKey, string localizationKey = null, LocalizationHelper localizationHelper = null)
        {
            RecipeKey          = itemName;
            RewardKey          = rewardKey;
            LocalizationHelper = localizationHelper;
            LocalizationKey    = localizationKey;

            if (ServerManager.RecipeStorage.TryGetRecipe(new Recipes.RecipeKey(itemName), out var recipe))
            {
                Recipe = recipe;
                ServerManager.RecipeStorage.AddScienceRequirement(Recipe);
            }
            else
            {
                APILogger.Log(ChatColor.red, "Item " + itemName + " recipe not found. unable to create RecipeUnlockReward for reward key " + rewardKey);
            }

            if (LocalizationHelper == null)
            {
                LocalizationHelper = new LocalizationHelper(GameInitializer.NAMESPACE, "Quests");
            }

            if (string.IsNullOrEmpty(LocalizationKey))
            {
                LocalizationKey = nameof(RecipeUnlockReward);
            }
        }
Beispiel #2
0
        //Ref menu is added for change LocalStorage -> avoid client error
        public static bool LoadItem(JSONNode item, ref NetworkMenu menu, Players.Player player, out List <IItem> menuItem)
        {
            string itemType = item.GetAs <string>("type").Trim().ToLower();
            bool   found    = false;

            menuItem = null;

            switch (itemType)
            {
            case "patchnotes":
                if (item.TryGetAsOrDefault <string>("mod", out string mod, ""))
                {
                    var info = default(JSONNode);

                    foreach (var modJson in GameInitializer.AllModInfos.Values)
                    {
                        if (modJson.TryGetAs("name", out string modName) && string.Equals(mod, modName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            info = modJson;
                            break;
                        }
                    }

                    if (info.TryGetAs <JSONNode>("patchnotes", out var patchNotesJson))
                    {
                        int i = 0;
                        menuItem = new List <IItem>();

                        foreach (var node in patchNotesJson.LoopArray())
                        {
                            i++;

                            node.TryGetAsOrDefault("version", out string version, "Undefined");
                            menuItem.Add(new Label(new LabelData("Version " + version, UnityEngine.TextAnchor.MiddleLeft, 24, LabelData.ELocalizationType.None)));

                            if (node.TryGetAs <JSONNode>("notes", out var versionNotesJson))
                            {
                                foreach (var note in versionNotesJson.LoopArray())
                                {
                                    menuItem.Add(new Label(new LabelData("    * " + note.ToString().Replace("\"", ""), UnityEngine.TextAnchor.MiddleLeft, 14, LabelData.ELocalizationType.None)));
                                }
                            }

                            if (i > 10)
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    APILogger.Log(ChatColor.red, "found patchnotes wiki item but mod property was not found");
                }

                found = true;
                break;
Beispiel #3
0
        public static IRoamingJobObjective GetCallbacks(string objectiveName)
        {
            if (ObjectiveCallbacks.ContainsKey(objectiveName))
            {
                return(ObjectiveCallbacks[objectiveName]);
            }

            APILogger.Log($"Unknown objective {objectiveName}.");
            return(null);
        }
Beispiel #4
0
        public static void AfterItemTypesDefined()
        {
            APILogger.Log("{0} objective types loaded", ObjectiveCallbacks.Count);

            foreach (var cKvp in _loadedColonies)
            {
                var c = cKvp.Key;
                var n = cKvp.Value;

                if (n.TryGetChild(GameInitializer.NAMESPACE + ".Objectives", out var objectivesNode))
                {
                    lock (Objectives)
                    {
                        int countLoaded = 0;
                        foreach (var node in objectivesNode.LoopArray())
                        {
                            try
                            {
                                RegisterRoamingJobState(c, new RoamingJobState(node, c));
                                countLoaded++;
                            }
                            catch (Exception ex)
                            {
                                APILogger.LogError(ex, node.ToString());
                            }
                        }

                        if (Objectives.ContainsKey(c))
                        {
                            APILogger.LogToFile($"{countLoaded} of {Objectives[c].Count} objectives loaded from save for {c.ColonyID}!");
                        }
                        else
                        {
                            APILogger.LogToFile($"No objectives found in save for {c.ColonyID}.");
                        }
                    }
                }
                else
                {
                    APILogger.LogToFile($"No objectives found in save for {c.ColonyID}.");
                }
            }
        }
        public void AfterWorldLoad()
        {
            foreach (OperationType verb in Enum.GetValues(typeof(OperationType)))
            {
                ApiCallbacks.Add(verb, new Dictionary <string, Tuple <object, MethodInfo> >(StringComparer.InvariantCultureIgnoreCase));
            }

            foreach (var ass in LoadedAssembalies)
            {
                var instance = Activator.CreateInstance(ass);

                foreach (var method in ass.GetMethods())
                {
                    foreach (var someAtt in method.GetCustomAttributes(true))
                    {
                        if (someAtt is PandaHttp pandaGet)
                        {
                            if (ApiCallbacks[pandaGet.RestVerb].ContainsKey(pandaGet.Route))
                            {
                                APILogger.Log(ChatColor.red, $"Route {pandaGet.Route} already exists for virb {pandaGet.RestVerb}. Overriding existing registered {ApiCallbacks[pandaGet.RestVerb][pandaGet.Route].Item2.Name} with {method.Name}");
                            }

                            ApiCallbacks[pandaGet.RestVerb][pandaGet.Route] = Tuple.Create(instance, method);

                            if (!Endpoints.ContainsKey(pandaGet.Route))
                            {
                                Endpoints.Add(pandaGet.Route, new Dictionary <OperationType, Tuple <string, MethodInfo> >());
                            }

                            Endpoints[pandaGet.Route][pandaGet.RestVerb] = Tuple.Create(pandaGet.Description, method);
                        }
                    }
                }
            }

            _listenThread = new Thread(new ThreadStart(Listen));
            _listenThread.IsBackground = true;
            _listenThread.Start();
        }
Beispiel #6
0
        public static void AddOres()
        {
            var settings = GameInitializer.GetJSONSettingPaths(GameInitializer.NAMESPACE + ".OreLayers");

            if (settings.Count == 0)
            {
                APILogger.Log("No Ore layers loaded.");
                return;
            }

            foreach (var modInfo in settings)
            {
                foreach (var path in modInfo.Value)
                {
                    var newMenu = JSON.Deserialize(modInfo.Key + "/" + path);

                    if (LoadedOres == null)
                    {
                        LoadedOres = newMenu;
                    }
                    else
                    {
                        LoadedOres.Merge(newMenu);
                    }
                }
            }

            try
            {
                var terrainGen = ServerManager.TerrainGenerator as TerrainGenerator;
                var stoneGen   = terrainGen.FinalChunkModifier as TerrainGenerator.InfiniteStoneLayerGenerator;
                var oreGen     = stoneGen.InnerGenerator as TerrainGenerator.OreLayersGenerator;

                foreach (var ore in LoadedOres.LoopArray())
                {
                    if (ore.TryGetAs("Chance", out byte chance) && ore.TryGetAs("Type", out string type) && ore.TryGetAs("Depth", out byte depth))
                    {
                        try
                        {
                            var item = ItemTypes.GetType(type);

                            ore.TryGetAsOrDefault("ScienceBiome", out string scienceBiome, null);

                            if (item != null && item.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id)
                            {
                                oreGen.AddLayer(new TerrainGenerator.Settings.OreLayer()
                                {
                                    Depth = depth, Type = item.Name, Chance = chance, ScienceBiome = scienceBiome
                                });
                            }
                            else
                            {
                                APILogger.Log(ChatColor.yellow, "Unable to find item {0}", type);
                            }
                        }
                        catch (Exception ex)
                        {
                            APILogger.LogError(ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                APILogger.LogError(ex);
            }
        }
Beispiel #7
0
        public TransportManager.ETransportUpdateResult Update()
        {
            if (_removed)
            {
                return(TransportManager.ETransportUpdateResult.Remove);
            }

            var currentPositionInt = new Pipliz.Vector3Int(Position);
            var heightFromTrack    = _idealHeightFromTrack;

            if (TrackPosition == Pipliz.Vector3Int.zero)
            {
                for (int i = -1; i > _idealHeightFromTrack * -1; i--)
                {
                    var trackPos = currentPositionInt.Add(0, i, 0);
                    if (World.TryGetTypeAt(trackPos, out ItemTypes.ItemType possibleTrack) &&
                        ConnectedBlockSystem.BlockLookup.TryGetValue(possibleTrack.Name, out var track) &&
                        track.ConnectedBlock.CalculationType == _trackCalculationType.name &&
                        TrainType.ConnectedBlock.BlockType == track.ConnectedBlock.BlockType)
                    {
                        heightFromTrack = i * -1;
                        TrackPosition   = trackPos;
                        break;
                    }
                }
            }

            if (heightFromTrack != _idealHeightFromTrack)
            {
                Position = currentPositionInt.Add(0, heightFromTrack, 0).Vector;
                _meshedVehicleDescription.Object.SendMoveToInterpolated(Position, Quaternion.identity, (float)GetDelayMillisecondsToNextUpdate() / 1000f, _animatedObject.ObjSettings);
            }
            else if (TrackPosition != Pipliz.Vector3Int.zero)
            {
                bool    moved        = false;
                ICSType trainStation = null;

                if (_trainMoveTime < TimeCycle.TotalHours)
                {
                    if (_minStopNextTime < TimeCycle.TotalHours)
                    {
                        foreach (var stationSide in _trackCalculationType.AvailableBlockSides)
                        {
                            var stationCheck = TrackPosition.GetBlockOffset(stationSide);

                            if (World.TryGetTypeAt(stationCheck, out ItemTypes.ItemType possibleStation) &&
                                ItemCache.CSItems.TryGetValue(possibleStation.Name, out var station) &&
                                station.TrainStationSettings != null &&
                                station.TrainStationSettings.BlockType == TrainType.ConnectedBlock.BlockType)
                            {
                                trainStation = station;

                                foreach (var kvp in RoamingJobManager.Objectives.Values)
                                {
                                    if (kvp.TryGetValue(trainStation.TrainStationSettings.ObjectiveCategory, out var locDic) &&
                                        locDic.TryGetValue(stationCheck, out var roamingJobState))
                                    {
                                        var manaNeeded = RoamingJobState.GetActionsMaxEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, roamingJobState.Colony, TrainType.TrainConfiguration.RoamingJobCategory) - _energy;

                                        var  existing = roamingJobState.GetActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName);
                                        bool isWorked = true;

                                        try
                                        {
                                            if (roamingJobState.Colony.JobFinder.JobsData != null)
                                            {
                                                foreach (var job in roamingJobState.Colony.JobFinder.JobsData.OpenJobs)
                                                {
                                                    try
                                                    {
                                                        if (job != null && job.GetJobLocation() == stationCheck)
                                                        {
                                                            isWorked = false;
                                                            break;
                                                        }
                                                    }
                                                    catch { }
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            if (roamingJobState.Colony.JobFinder == null)
                                            {
                                                APILogger.Log("roamingJobState.Colony.JobFinder == null");
                                            }

                                            if (roamingJobState.Colony.JobFinder.JobsData == null)
                                            {
                                                APILogger.Log("roamingJobState.Colony.JobFinder.JobsData == null");
                                            }

                                            if (roamingJobState.Colony.JobFinder.JobsData.OpenJobs == null)
                                            {
                                                APILogger.Log("roamingJobState.Colony.JobFinder.JobsData.OpenJobs == null");
                                            }

                                            APILogger.LogError(ex);
                                        }

                                        if (!isWorked)
                                        {
                                            Indicator.SendIconIndicatorNear(stationCheck.Add(0, 1, 0).Vector, new IndicatorState(10, "npcicon", true, false));
                                        }
                                        else if (existing > 0)
                                        {
                                            if (existing >= manaNeeded)
                                            {
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, manaNeeded);
                                                _energy = RoamingJobState.GetActionsMaxEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, roamingJobState.Colony, TrainType.TrainConfiguration.RoamingJobCategory);
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.DurabilityActionEnergyName, .01f);
                                            }
                                            else
                                            {
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, existing);
                                                _energy += existing;
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.DurabilityActionEnergyName, .01f);
                                            }

                                            Indicator.SendIconIndicatorNear(stationCheck.Add(0, 1, 0).Vector, new IndicatorState(10, TrainType.TrainConfiguration.EnergyType));
                                            _minStopNextTime = TimeCycle.TotalHours + 2;
                                            _trainMoveTime   = TimeCycle.TotalHours + 1;
                                            existing         = roamingJobState.GetActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName);
                                        }
                                        else
                                        {
                                            Indicator.SendIconIndicatorNear(stationCheck.Add(0, 1, 0).Vector, new IndicatorState(10, TrainType.TrainConfiguration.EnergyType, true, false));
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (trainStation == null && _energy > 0)
                    {
                        foreach (var side in _trackCalculationType.AvailableBlockSides)
                        {
                            var searchSide = TrackPosition.GetBlockOffset(side);
                            var proposePos = currentPositionInt.GetBlockOffset(side).Vector;

                            if (World.TryGetTypeAt(searchSide, out ItemTypes.ItemType possibleTrack) &&
                                ConnectedBlockSystem.BlockLookup.TryGetValue(possibleTrack.Name, out var track) &&
                                track.ConnectedBlock.CalculationType == _trackCalculationType.name &&
                                TrainType.ConnectedBlock.BlockType == track.ConnectedBlock.BlockType &&
                                proposePos != _prevPosition)
                            {
                                _prevPosition = Position;
                                TrackPosition = searchSide;
                                Position      = currentPositionInt.GetBlockOffset(side).Vector;
                                _meshedVehicleDescription.Object.SendMoveToInterpolated(Position, Quaternion.identity, (float)GetDelayMillisecondsToNextUpdate() / 1000f, _animatedObject.ObjSettings);
                                _energy -= ManaCostPerBlock;

                                if (_energy < 0)
                                {
                                    _energy = 0;
                                }

                                ChunkQueue.QueueBannerBox(TrackPosition.Add(-30, -30, -30).ToChunk(), TrackPosition.Add(30, 30, 30).ToChunk());

                                moved = true;
                                break;
                            }
                        }
                    }
                }

                if (!moved)
                {
                    _meshedVehicleDescription.Object.SendMoveToInterpolated(Position, Quaternion.identity, (float)GetDelayMillisecondsToNextUpdate() / 1000f, _animatedObject.ObjSettings);
                }

                if (!moved && _energy > 0)
                {
                    _prevPosition = Vector3.zero;
                }

                if (!moved && _energy <= 0)
                {
                    _trainMoveTime = 0;
                    Indicator.SendIconIndicatorNear(new Pipliz.Vector3Int(Position).Add(0, 2, 0).Vector, new IndicatorState((float)GetDelayMillisecondsToNextUpdate() / 1000f, TrainType.TrainConfiguration.EnergyType, true, false));
                }
            }

            return(TransportManager.ETransportUpdateResult.KeepUpdating);
        }
        public static void OnUpdate()
        {
            if (!World.Initialized)
            {
                return;
            }

            var secondsSinceStartDouble = Time.SecondsSinceStartDouble;

            if (World.Initialized)
            {
                if (!TimeCycle.IsDay &&
                    !BossActive &&
                    _nextBossUpdateTime <= secondsSinceStartDouble)
                {
                    BossActive = true;
                    var bossType = GetMonsterType();

                    if (bossType != null)
                    {
                        _monsterManager.CurrentPandaBoss = bossType;
                        ServerManager.PathingManager.QueueAction(_monsterManager);
                        _justQueued = secondsSinceStartDouble + 5;

                        if (Players.CountConnected != 0)
                        {
                            APILogger.Log(ChatColor.yellow, $"Boss Active! Boss is: {bossType.name}");
                        }
                    }
                    else
                    {
                        BossActive = false;
                        GetNextBossSpawnTime();
                    }
                }

                if (BossActive && _justQueued < secondsSinceStartDouble)
                {
                    var turnOffBoss = true;

                    if (_pandaBossesSpawnQueue.Count > 0)
                    {
                        var pandaboss = _pandaBossesSpawnQueue.Dequeue();
                        var cs        = ColonyState.GetColonyState(pandaboss.OriginalGoal);
                        BossSpawned?.Invoke(MonsterTracker.MonsterSpawner, new BossSpawnedEvent(cs, pandaboss));

                        ModLoader.Callbacks.OnMonsterSpawned.Invoke(pandaboss);
                        MonsterTracker.Add(pandaboss);
                        cs.ColonyRef.OnZombieSpawn(true);
                        cs.FaiedBossSpawns = 0;
                        PandaChat.Send(cs, _localizationHelper, $"[{pandaboss.name}] {pandaboss.AnnouncementText}", ChatColor.red);

                        if (!string.IsNullOrEmpty(pandaboss.AnnouncementAudio))
                        {
                            cs.ColonyRef.ForEachOwner(o => AudioManager.SendAudio(o.Position, pandaboss.AnnouncementAudio));
                        }
                    }

                    foreach (var colony in ServerManager.ColonyTracker.ColoniesByID.Values)
                    {
                        var bannerGoal = colony.Banners.FirstOrDefault();
                        var cs         = ColonyState.GetColonyState(colony);

                        if (bannerGoal != null &&
                            cs.BossesEnabled &&
                            cs.ColonyRef.OwnerIsOnline())
                        {
                            if (SpawnedBosses.ContainsKey(cs) &&
                                SpawnedBosses[cs].IsValid &&
                                SpawnedBosses[cs].CurrentHealth > 0)
                            {
                                if (colony.TemporaryData.GetAsOrDefault("BossIndicator", 0) < Time.SecondsSinceStartInt)
                                {
                                    Indicator.SendIconIndicatorNear(new Vector3Int(SpawnedBosses[cs].Position),
                                                                    SpawnedBosses[cs].ID,
                                                                    new IndicatorState(1, ItemId.GetItemId(GameInitializer.NAMESPACE + ".Poisoned").Id,
                                                                                       false, false));

                                    colony.TemporaryData.SetAs("BossIndicator", Time.SecondsSinceStartInt + 1);
                                }

                                turnOffBoss = false;
                            }
                        }


                        if (turnOffBoss)
                        {
                            if (Players.CountConnected != 0 && SpawnedBosses.Count != 0)
                            {
                                APILogger.Log(ChatColor.yellow, $"All bosses cleared!");
                                var boss = SpawnedBosses.FirstOrDefault().Value;
                                PandaChat.SendToAll($"[{boss.name}] {boss.DeathText}", _localizationHelper, ChatColor.red);
                            }

                            BossActive = false;
                            SpawnedBosses.Clear();
                            GetNextBossSpawnTime();
                        }
                    }
                }
            }
        }
Beispiel #9
0
        public override void Dispose()
        {
            string exceptionMessage = null;

            try
            {
                _webCache.Dispose();
            }
            catch (Exception e)
            {
                exceptionMessage = e.Message;
                throw;
            }
            finally
            {
                try
                {
                    if (_debugConfigurations.IsInLoggingInterval())
                    {
                        APILogItem logItem = new APILogItem();
                        logItem.Signature        = "Dispose()";
                        logItem.ExceptionMessage = exceptionMessage;
                        _apiLogger.Log(logItem);
                    }
                    _apiLogger.Dispose();
                }
                catch (Exception)
                { }
            }
        }
        public void Listen()
        {
            HttpListener listener = new HttpListener();
            var          url      = "http://" + APIConfiguration.CSModConfiguration.GetorDefault("PandaAPIAddress", "*") + ":" + APIConfiguration.CSModConfiguration.GetorDefault("PandaAPIPort", 10984) + "/";

            listener.Prefixes.Add(url);
            listener.Start();
            APILogger.Log(ChatColor.green, "Pandaros Rest API now listening on: {0}", url);

            while (true)
            {
                HttpListenerContext context = listener.GetContext();

                if (Enum.TryParse(context.Request.HttpMethod, true, out OperationType verb) && ApiCallbacks.TryGetValue(verb, out var callbacks))
                {
                    ThreadPool.QueueUserWorkItem((_) =>
                    {
                        string methodName = context.Request.Url.AbsolutePath;

                        try
                        {
                            if (callbacks.TryGetValue(methodName, out var method))
                            {
                                var response    = default(RestResponse);
                                var mehodParams = method.Item2.GetParameters();
                                string bodyStr  = string.Empty;

                                if (context.Request.HasEntityBody)
                                {
                                    using (StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8, true, 1024, true))
                                    {
                                        bodyStr = reader.ReadToEnd();
                                    }
                                }

                                if (mehodParams.Length > 0)
                                {
                                    foreach (var param in mehodParams)
                                    {
                                        if (param.Name == "body")
                                        {
                                            continue;
                                        }

                                        if (!context.Request.QueryString.AllKeys.Any(k => k == param.Name))
                                        {
                                            context.Response.StatusCode        = 422;
                                            context.Response.StatusDescription = "Missing Parameter. Expected: " + param.Name;
                                            context.Response.OutputStream.Close();
                                            return;
                                        }
                                    }

                                    foreach (var param in context.Request.QueryString.AllKeys)
                                    {
                                        if (!mehodParams.Any(k => k.Name == param))
                                        {
                                            context.Response.StatusCode        = 422;
                                            context.Response.StatusDescription = "Unknown Parameter: " + param;
                                            context.Response.OutputStream.Close();
                                            return;
                                        }
                                    }

                                    object[] requestParams = mehodParams
                                                             .Select((p, i) =>
                                    {
                                        if (p.Name == "body")
                                        {
                                            return(bodyStr);
                                        }

                                        return(Convert.ChangeType(context.Request.QueryString[p.Name], p.ParameterType));
                                    })
                                                             .ToArray();

                                    response = method.Item2.Invoke(method.Item1, requestParams) as RestResponse;
                                }
                                else
                                {
                                    response = method.Item2.Invoke(method.Item1, null) as RestResponse;
                                }

                                if (response != null)
                                {
                                    context.Response.ContentType     = response.ContentType;
                                    context.Response.ContentLength64 = response.Content.Length;
                                    context.Response.StatusCode      = response.HttpCode;
                                    context.Response.OutputStream.Write(response.Content, 0, response.Content.Length);
                                }
                                else
                                {
                                    throw new InvalidCastException("All methods decorated with PandaHttp must return type RestResponse.");
                                }
                            }
                            else
                            {
                                context.Response.StatusCode        = (int)HttpStatusCode.NotFound;
                                context.Response.StatusDescription = "No method registered with method name: " + methodName;
                            }
                        }
                        catch (Exception ex)
                        {
                            APILogger.LogError(ex);
                            context.Response.StatusCode = 500;
                        }

                        context.Response.OutputStream.Close();
                    });
                }
                else
                {
                    context.Response.StatusCode        = (int)HttpStatusCode.NotFound;
                    context.Response.StatusDescription = "No rest verb registered with Http Mehtod: " + context.Request.HttpMethod;
                    context.Response.OutputStream.Close();
                }
            }
        }
        public void AddItemTypes(Dictionary <string, ItemTypesServer.ItemTypeRaw> itemTypes)
        {
            var i = 0;

            foreach (var item in LoadedAssembalies)
            {
                try
                {
                    if (Activator.CreateInstance(item) is ICSType itemType &&
                        !string.IsNullOrEmpty(itemType.name))
                    {
                        ItemCache.CSItems[itemType.name] = itemType;

                        var permutations = ConnectedBlockCalculator.GetPermutations(itemType);

                        foreach (var permutation in permutations)
                        {
                            ItemCache.CSItems[permutation.name] = permutation;
                        }
                    }
                }
                catch (Exception ex)
                {
                    APILogger.LogError(ex);
                }
            }

            var settings = GameInitializer.GetJSONSettingPaths(GameInitializer.NAMESPACE + ".CSItems");

            foreach (var modInfo in settings)
            {
                foreach (var path in modInfo.Value)
                {
                    try
                    {
                        var jsonFile = JSON.Deserialize(modInfo.Key + "/" + path);

                        if (jsonFile.NodeType == NodeType.Object && jsonFile.ChildCount > 0)
                        {
                            foreach (var item in jsonFile.LoopObject())
                            {
                                foreach (var property in _fixRelativePaths)
                                {
                                    if (item.Value.TryGetAs(property, out string propertyPath) && propertyPath.StartsWith("./"))
                                    {
                                        item.Value[property] = new JSONNode(modInfo.Key + "/" + propertyPath.Substring(2));
                                    }
                                }

                                if (item.Value.TryGetAs("Durability", out int durability))
                                {
                                    var ma = item.Value.JsonDeerialize <MagicArmor>();
                                    ItemCache.CSItems[ma.name] = ma;
                                }
                                else if (item.Value.TryGetAs("WepDurability", out bool wepDurability))
                                {
                                    var mw = item.Value.JsonDeerialize <MagicWeapon>();
                                    ItemCache.CSItems[mw.name] = mw;
                                }
                                else if (item.Value.TryGetAs("IsMagical", out bool isMagic))
                                {
                                    var mi = item.Value.JsonDeerialize <PlayerMagicItem>();
                                    ItemCache.CSItems[mi.name] = mi;
                                }
                                else
                                {
                                    var newItem = item.Value.JsonDeerialize <CSType>();
                                    ItemCache.CSItems[newItem.name] = newItem;

                                    var permutations = ConnectedBlockCalculator.GetPermutations(newItem);

                                    foreach (var permutation in permutations)
                                    {
                                        ItemCache.CSItems[permutation.name] = permutation;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        APILogger.LogError(ex);
                    }
                }
            }

            foreach (var itemType in ItemCache.CSItems.Values)
            {
                if (itemType.TrainConfiguration != null && itemType.TrainConfiguration.playerSeatOffset != null)
                {
                    Transportation.Train.TrainTypes[itemType.name] = itemType;
                }

                ConnectedBlockSystem.AddConnectedBlock(itemType);

                var rawItem = new ItemTypesServer.ItemTypeRaw(itemType.name, itemType.JsonSerialize());

                if (itemTypes.ContainsKey(itemType.name))
                {
                    APILogger.Log(ChatColor.yellow, "Item {0} already loaded...Overriding item.", itemType.name);
                    itemTypes[itemType.name] = rawItem;
                }
                else
                {
                    itemTypes.Add(itemType.name, rawItem);
                }

                if (itemType.StaticItemSettings != null && !string.IsNullOrWhiteSpace(itemType.StaticItemSettings.Name))
                {
                    StaticItems.List.Add(itemType.StaticItemSettings);
                }

                if (itemType is IArmor ma && ma.Durability > 0)
                {
                    ArmorFactory.ArmorLookup.Add(rawItem.ItemIndex, ma);
                }