Beispiel #1
0
        public override void Start(ICoreAPI api)
        {
            this.api = api;

            worldConfig = api.World.Config;
            if (worldConfig == null)
            {
                worldConfig = new TreeAttribute();
            }

            List <IAsset> entries = api.Assets.GetMany("patches/");

            int appliedCount        = 0;
            int notfoundCount       = 0;
            int errorCount          = 0;
            int totalCount          = 0;
            int unmetConditionCount = 0;

            foreach (IAsset asset in entries)
            {
                JsonPatch[] patches = null;
                try
                {
                    patches = asset.ToObject <JsonPatch[]>();
                } catch (Exception e)
                {
                    api.World.Logger.Error("Failed loading patches file {0}: {1}", asset.Location, e);
                }

                for (int j = 0; patches != null && j < patches.Length; j++)
                {
                    JsonPatch patch = patches[j];
                    if (patch.Condition != null)
                    {
                        IAttribute attr = worldConfig[patch.Condition.When];
                        if (attr == null)
                        {
                            continue;
                        }

                        if (patch.Condition.useValue)
                        {
                            patch.Value = new JsonObject(JToken.Parse(attr.ToJsonToken()));
                        }
                        else
                        {
                            if (!patch.Condition.IsValue.Equals(attr.GetValue() + "", StringComparison.InvariantCultureIgnoreCase))
                            {
                                unmetConditionCount++;
                                continue;
                            }
                        }
                    }

                    totalCount++;
                    ApplyPatch(j, asset.Location, patch, ref appliedCount, ref notfoundCount, ref errorCount);
                }
            }

            StringBuilder sb = new StringBuilder();

            sb.Append("JsonPatch Loader: ");

            if (totalCount == 0)
            {
                sb.Append(Lang.Get("Nothing to patch", totalCount));
            }
            else
            {
                sb.Append(Lang.Get("{0} patches total", totalCount));

                if (appliedCount > 0)
                {
                    sb.Append(Lang.Get(", successfully applied {0} patches", appliedCount));
                }

                if (notfoundCount > 0)
                {
                    sb.Append(Lang.Get(", missing files on {0} patches", notfoundCount));
                }

                if (unmetConditionCount > 0)
                {
                    sb.Append(Lang.Get(", unmet conditions on {0} patches", unmetConditionCount));
                }

                if (errorCount > 0)
                {
                    sb.Append(Lang.Get(", had errors on {0} patches", errorCount));
                }
                else
                {
                    sb.Append(Lang.Get(", no errors", errorCount));
                }
            }


            api.World.Logger.Notification(sb.ToString());
            base.Start(api);
        }
Beispiel #2
0
        private void ApplyPatch(int patchIndex, AssetLocation patchSourcefile, JsonPatch jsonPatch, ref int applied, ref int notFound, ref int errorCount)
        {
            if (jsonPatch.SideType != EnumAppSide.Universal && jsonPatch.SideType != api.Side)
            {
                return;
            }

            var path = jsonPatch.File.Path;

            if (!path.EndsWith(".json"))
            {
                path += ".json";
            }

            var asset = api.Assets.TryGet(path);

            if (asset == null)
            {
                api.World.Logger.VerboseDebug("Patch {0} in {1}: File {2} not found", patchIndex, patchSourcefile, path);
                notFound++;
                return;
            }

            Operation op = null;

            switch (jsonPatch.Op)
            {
            case EnumJsonPatchOp.Add:
                if (jsonPatch.Value == null)
                {
                    api.World.Logger.Error("Patch {0} in {1} failed probably because it is an add operation and the value property is not set or misspelled", patchIndex, patchSourcefile);
                    errorCount++;
                    return;
                }
                op = new AddOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), Value = jsonPatch.Value.Token
                };
                break;

            case EnumJsonPatchOp.Remove:
                op = new RemoveOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path)
                };
                break;

            case EnumJsonPatchOp.Replace:
                if (jsonPatch.Value == null)
                {
                    api.World.Logger.Error("Patch {0} in {1} failed probably because it is a replace operation and the value property is not set or misspelled", patchIndex, patchSourcefile);
                    errorCount++;
                    return;
                }

                op = new ReplaceOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), Value = jsonPatch.Value.Token
                };
                break;

            case EnumJsonPatchOp.Copy:
                op = new CopyOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), FromPath = new JsonPointer(jsonPatch.FromPath)
                };
                break;

            case EnumJsonPatchOp.Move:
                op = new MoveOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), FromPath = new JsonPointer(jsonPatch.FromPath)
                };
                break;
            }

            PatchDocument patchdoc = new PatchDocument(op);
            JToken        token    = null;

            try
            {
                token = JToken.Parse(asset.ToText());
            }
            catch (Exception e)
            {
                api.World.Logger.Error("Patch {0} in {1} failed probably because the syntax of the value is broken: {2}", patchIndex, patchSourcefile, e);
                errorCount++;
                return;
            }

            try
            {
                patchdoc.ApplyTo(token);
            }
            catch (Tavis.PathNotFoundException p)
            {
                api.World.Logger.Error("Patch {0} in {1} failed because supplied path {2} is invalid: {3}", patchIndex, patchSourcefile, jsonPatch.Path, p.Message);
                errorCount++;
                return;
            }
            catch (Exception e)
            {
                api.World.Logger.Error("Patch {0} in {1} failed, following Exception was thrown: {2}", patchIndex, patchSourcefile, e.Message);
                errorCount++;
                return;
            }

            string text = token.ToString();

            asset.Data = System.Text.Encoding.UTF8.GetBytes(text);

            applied++;
        }
Beispiel #3
0
        private void ApplyPatch(int patchIndex, AssetLocation patchSourcefile, JsonPatch jsonPatch, ref int applied, ref int notFound, ref int errorCount)
        {
            EnumAppSide targetSide = jsonPatch.Side == null ? jsonPatch.File.Category.SideType : (EnumAppSide)jsonPatch.Side;

            if (targetSide != EnumAppSide.Universal && jsonPatch.Side != api.Side)
            {
                return;
            }

            var loc = jsonPatch.File.Clone();

            if (jsonPatch.File.Path.EndsWith("*"))
            {
                List <IAsset> assets = api.Assets.GetMany(jsonPatch.File.Path.TrimEnd('*'), jsonPatch.File.Domain, false);
                foreach (var val in assets)
                {
                    jsonPatch.File = val.Location;
                    ApplyPatch(patchIndex, patchSourcefile, jsonPatch, ref applied, ref notFound, ref errorCount);
                }

                jsonPatch.File = loc;

                return;
            }



            if (!loc.Path.EndsWith(".json"))
            {
                loc.Path += ".json";
            }

            var asset = api.Assets.TryGet(loc);

            if (asset == null)
            {
                if (jsonPatch.File.Category == null)
                {
                    api.World.Logger.VerboseDebug("Patch {0} in {1}: File {2} not found. Wrong asset category", patchIndex, patchSourcefile, loc);
                }
                else
                {
                    EnumAppSide catSide = jsonPatch.File.Category.SideType;
                    if (catSide != EnumAppSide.Universal && api.Side != catSide)
                    {
                        api.World.Logger.VerboseDebug("Patch {0} in {1}: File {2} not found. Hint: This asset is usually only loaded {3} side", patchIndex, patchSourcefile, loc, catSide);
                    }
                    else
                    {
                        api.World.Logger.VerboseDebug("Patch {0} in {1}: File {2} not found", patchIndex, patchSourcefile, loc);
                    }
                }


                notFound++;
                return;
            }

            Operation op = null;

            switch (jsonPatch.Op)
            {
            case EnumJsonPatchOp.Add:
                if (jsonPatch.Value == null)
                {
                    api.World.Logger.Error("Patch {0} in {1} failed probably because it is an add operation and the value property is not set or misspelled", patchIndex, patchSourcefile);
                    errorCount++;
                    return;
                }
                op = new AddOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), Value = jsonPatch.Value.Token
                };
                break;

            case EnumJsonPatchOp.Remove:
                op = new RemoveOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path)
                };
                break;

            case EnumJsonPatchOp.Replace:
                if (jsonPatch.Value == null)
                {
                    api.World.Logger.Error("Patch {0} in {1} failed probably because it is a replace operation and the value property is not set or misspelled", patchIndex, patchSourcefile);
                    errorCount++;
                    return;
                }

                op = new ReplaceOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), Value = jsonPatch.Value.Token
                };
                break;

            case EnumJsonPatchOp.Copy:
                op = new CopyOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), FromPath = new JsonPointer(jsonPatch.FromPath)
                };
                break;

            case EnumJsonPatchOp.Move:
                op = new MoveOperation()
                {
                    Path = new Tavis.JsonPointer(jsonPatch.Path), FromPath = new JsonPointer(jsonPatch.FromPath)
                };
                break;
            }

            PatchDocument patchdoc = new PatchDocument(op);
            JToken        token    = null;

            try
            {
                token = JToken.Parse(asset.ToText());
            }
            catch (Exception e)
            {
                api.World.Logger.Error("Patch {0} (target: {3}) in {1} failed probably because the syntax of the value is broken: {2}", patchIndex, patchSourcefile, e, loc);
                errorCount++;
                return;
            }

            try
            {
                patchdoc.ApplyTo(token);
            }
            catch (Tavis.PathNotFoundException p)
            {
                api.World.Logger.Error("Patch {0} (target: {4}) in {1} failed because supplied path {2} is invalid: {3}", patchIndex, patchSourcefile, jsonPatch.Path, p.Message, loc);
                errorCount++;
                return;
            }
            catch (Exception e)
            {
                api.World.Logger.Error("Patch {0} (target: {3}) in {1} failed, following Exception was thrown: {2}", patchIndex, patchSourcefile, e.Message, loc);
                errorCount++;
                return;
            }

            string text = token.ToString();

            asset.Data = System.Text.Encoding.UTF8.GetBytes(text);

            applied++;
        }
        public override void AssetsLoaded(ICoreAPI api)    // This is done before assets and items are registerd etc, and before remapping, because of the ExecuteOrder, and (server-side) because of the position of ModHandler early in the ServerSystems list
        {
            this.api = api;

            worldConfig = api.World.Config;
            if (worldConfig == null)
            {
                worldConfig = new TreeAttribute();
            }

            List <IAsset> entries = api.Assets.GetMany("patches/");

            int appliedCount        = 0;
            int notfoundCount       = 0;
            int errorCount          = 0;
            int totalCount          = 0;
            int unmetConditionCount = 0;

            HashSet <string> loadedModIds = new HashSet <string>(api.ModLoader.Mods.Select((m) => m.Info.ModID).ToList());

            foreach (IAsset asset in entries)
            {
                JsonPatch[] patches = null;
                try
                {
                    patches = asset.ToObject <JsonPatch[]>();
                } catch (Exception e)
                {
                    api.Logger.Error("Failed loading patches file {0}: {1}", asset.Location, e);
                }

                for (int j = 0; patches != null && j < patches.Length; j++)
                {
                    JsonPatch patch = patches[j];
                    if (patch.Condition != null)
                    {
                        IAttribute attr = worldConfig[patch.Condition.When];
                        if (attr == null)
                        {
                            continue;
                        }

                        if (patch.Condition.useValue)
                        {
                            patch.Value = new JsonObject(JToken.Parse(attr.ToJsonToken()));
                        }
                        else
                        {
                            if (!patch.Condition.IsValue.Equals(attr.GetValue() + "", StringComparison.InvariantCultureIgnoreCase))
                            {
                                api.Logger.VerboseDebug("Patch file {0}, patch {1}: Unmet IsValue condition ({2}!={3})", asset.Location, j, patch.Condition.IsValue, attr.GetValue() + "");
                                unmetConditionCount++;
                                continue;
                            }
                        }
                    }

                    if (patch.DependsOn != null)
                    {
                        bool enabled = true;

                        foreach (var dependence in patch.DependsOn)
                        {
                            bool loaded = loadedModIds.Contains(dependence.modid);
                            enabled = enabled && (loaded ^ dependence.invert);
                        }

                        if (!enabled)
                        {
                            unmetConditionCount++;
                            api.Logger.VerboseDebug("Patch file {0}, patch {1}: Unmet DependsOn condition ({2})", asset.Location, j, string.Join(",", patch.DependsOn.Select(pd => (pd.invert ? "!" : "") + pd.modid)));
                            continue;
                        }
                    }

                    totalCount++;
                    ApplyPatch(j, asset.Location, patch, ref appliedCount, ref notfoundCount, ref errorCount);
                }
            }

            StringBuilder sb = new StringBuilder();

            sb.Append("JsonPatch Loader: ");

            if (totalCount == 0)
            {
                sb.Append(Lang.Get("Nothing to patch", totalCount));
            }
            else
            {
                sb.Append(Lang.Get("{0} patches total", totalCount));

                if (appliedCount > 0)
                {
                    sb.Append(Lang.Get(", successfully applied {0} patches", appliedCount));
                }

                if (notfoundCount > 0)
                {
                    sb.Append(Lang.Get(", missing files on {0} patches", notfoundCount));
                }

                if (unmetConditionCount > 0)
                {
                    sb.Append(Lang.Get(", unmet conditions on {0} patches", unmetConditionCount));
                }

                if (errorCount > 0)
                {
                    sb.Append(Lang.Get(", had errors on {0} patches", errorCount));
                }
                else
                {
                    sb.Append(Lang.Get(", no errors", errorCount));
                }
            }

            api.Logger.Notification(sb.ToString());
            api.Logger.VerboseDebug("Patchloader finished");
        }