Project icon Patchly
Patchly

The Perfect Pure Patching Plugin

55 downloads
10 days agoUpdated June 7 at 03:53 AM
Game MechanicsTechnologyLibraryOptimizationUtility

Introduction

Updated Jun 2, 2026

Patchly - The Perfect Pure Patching Plugin

Patch JSON assets instead of rewriting them

Patchly lets one pack reach into another pack's asset and change only the fields it cares about, leaving everything else untouched. You drop a .patch file next to the asset you want to change, and Patchly merges it onto the resolved original.

TL;DR

In your pack, create a file at the same path as the asset you want to change, swapping .json for .patch.

To add the mana stat to

Server/Item/Items/Armor/Iron/Armor_Iron_Head.json

make this in your pack

Server/Item/Items/Armor/Iron/Armor_Iron_Head.patch

and set it to

{
  "Armor": {
    "StatModifiers": {
      "Mana": [{ "Amount": 126, "CalculationType": "Additive" }]
    }
  }
}

That's it. You've now patched some armor!

Patch syntax

A .patch is plain JSON. Every key you write is merged onto the matching key in the resolved base asset. Here is every rule at a glance, then each one explained.

FeatureExampleWhat it does
Deep merge (objects){ "A": { "B": 1 } }Only leaf B changes; sibling keys survive.
Replace array (default)"Categories": [...]Discards the parent's array, uses yours.
Append to array"Categories+": [...]Keeps the parent's entries, adds yours at the end.
Prepend to array"Categories-": [...]Keeps the parent's entries, adds yours at the front.
Fill if absent"Mana?": [...]Writes the value only if the key is missing; otherwise the base wins.
Extend by index"Recipes~": [ {}, {...} ]Merges into the base element at each position; {} changes nothing.
Extend by field"Children+": [ { "$Match": "Id", "Id": "Tools", ... } ]Finds the element whose field matches and merges into it.
Delete a key"DamageResistance": nullRemoves that key from the merged asset.
Gate on packs"$Requires": "Group:Name" or "Group:Name:>=1.2.0" or [...]Patch applies only if all named packs are installed (and satisfy the optional version range); otherwise skipped with a log line.
Win on conflicts"$Priority": 100Integer, default 0. Higher applies last and wins on conflicting fields.

An overview of their implementation is found here

Questions and Answers

QuestionAnswer
Where do I put the .patch?Same path as what you want to patch into. .json swapped for .patch.
Which packs can be patched?Every registered pack: folder, .zip, and .jar.
Does it hot-reload?Folder packs re-merge live on .patch edit. Zip/jar packs apply once at

Next steps

  • For Pack Developers - ship .patch files in an asset-only pack and require Patchly as a dependency.
  • For Mod Developers - bundle Patchly directly into your Java plugin with Gradle Shadow.
Powered byHytaleModding