A downloadable asset pack

Get this asset pack and 11 more for $59.93 USD
View bundle
Buy Now
On Sale!
40% Off
$9.99 $5.99 USD or more

Inventory Save Adapter is a GDScript add-on for Godot 4 that checks plain inventory data (named containers of indexed item stacks), turns it into versioned JSON snapshots, restores it, and can keep it in a standalone save file with a .bak fallback. This paid edition also includes an optional bridge for a save manager that provides save_slot and load_slot, a recipe guide and runnable examples. It is not an inventory UI and it does not replace your inventory plugin.

What it does

  • Containers and stacks. An inventory is a list of named containers (for example bag, equipment, hotbar). Each container has a capacity and indexed slots holding an item_id and a count, plus optional integer x/y coordinates. The coordinates are stored as numbers only: there is no grid or collision logic.
  • Validation, not coercion. Counts must be whole numbers from 1 to 2,147,483,647: zero, negative, fractional, boolean and overflowing counts are rejected. Capacity is 1 to 4096, with at most 64 containers and 65,536 occupied slots. IDs are 1 to 128 characters. Container IDs and slot indexes must be unique. Whole-number floats such as 3.0 (what JSON gives you) are accepted and stored as integers. A failed restore leaves your target object untouched.
  • Item allow-list and stack limits. Pass a list of known item IDs: unknown IDs are rejected by default, or dropped with a warning if you pass skip_unknown = true. Optional per-item stack_limits lower the maximum count.
  • Snapshots and JSON. snapshot / restore work on Dictionaries, to_json / from_json on text. Snapshots and restored data are deep copies; they do not share memory with your model.
  • Schema versions and migrations. Snapshots carry a schema_version (currently 1). You register sequential migration steps. A missing version or a malformed step result is ERR_INVALID_DATA; a missing step or a newer version is ERR_UNAVAILABLE. A snapshot from a newer version is refused, not guessed at.
  • Standalone file store. InventoryFileStore.write / read work on user://….json paths. Write validates before touching any file, writes a .tmp file, keeps the previous valid file as .bak, then replaces the main file. If the main file is missing or corrupt and a valid .bak exists, read returns the backup's data with recovered = true. Reading never rewrites files. Files over 4 MiB are rejected. This is a recoverable replacement, not a promise of fsync durability.
  • SaveKit bridge (paid only). SaveKitInventoryBridge has configure(provider, codec), save_inventory(slot_id, model, playtime) and load_inventory(slot_id, target, ...). It calls the provider's save_slot and load_slot, passes the provider's error and its recovered flag back to you, and does not call the provider when your model is invalid.
  • Recipe guide and examples (paid only). docs/recipe-guide.md covers bridge setup, unknown IDs, migrations, recovery, composing your own payload without the bridge, and mapping plain exported records ({position, id, quantity}) to slots. examples/ holds a bag / equipment / hotbar setup, a plain-record mapping and a stub save manager.

What you need

  • Godot 4. Written for 4.x; tested only on 4.7.2 (see "What was tested").
  • No other plugin is needed for the tests or the demo.
  • To use the bridge you need a save manager of your own. This download does not include GodotSaveKit or any other save manager. The bridge accepts an object that has save_slot(slot_id: String, data: Dictionary, playtime: float, screenshot_path: String) -> Error and load_slot(slot_id: String) -> Dictionary, where the returned Dictionary has error (int), data (Dictionary), meta (Dictionary), version (int) and recovered (bool). A reply of any other shape comes back as ERR_INVALID_DATA. GodotSaveKit's GSKSaveManager declares both methods. GodotSaveKit is a separate product: https://mustafawave286.gumroad.com/l/ucpdfx
  • You can skip the bridge and use the standalone file store, or put a snapshot into your own save payload (the recipe guide shows how).

What's in the box

The download is one zip, InventorySaveAdapter-v1.0.2.zip (29,193 bytes), 41 files, extracting into one folder named paid/.

  • Licences and documents (6): LICENSE, LICENSE-MIT.txt, LICENSE-PAID.txt, LICENCE.md (file-by-file licence table), README.md, CHANGELOG.md
  • Project metadata (2): plugin.cfg, project.godot
  • addons/inventory_save_lite/ (7, MIT core): inventory_data.gd, inventory_validator.gd, inventory_migrations.gd, inventory_codec.gd, inventory_file_store.gd, plugin.gd, plugin.cfg
  • addons/inventory_save_adapter/ (3, paid-only): savekit_inventory_bridge.gd, plugin.gd, plugin.cfg
  • docs/ (1, paid-only): recipe-guide.md
  • examples/ (3, paid-only): containers.gd, plugin_mapping.gd, savekit_stub.gd
  • demo/ (11, MIT): project.godot, main.tscn, main.gd, round_trip.gd, and its own copy of the core in demo/addons/inventory_save_lite/ (7 files)
  • tests/ (8): run_all.gd, test_codec.gd, test_validation.gd, test_migrations.gd, test_files.gd (MIT); run_paid.gd, test_savekit_bridge.gd, test_recipes.gd (paid-only)

Not included: GodotSaveKit or any other save manager, an inventory UI, item art, an autosave or slot manager.

Install and run

  • Extract the zip into an empty folder.
  • Demo: godot --headless --path paid/demo --import, then godot --headless --path paid/demo -s res://round_trip.gd. It prints PASS demo/round_trip.
  • Tests: godot --headless --path paid --import, then godot --headless --path paid -s res://tests/run_paid.gd. The last line should read SUMMARY checks=76 failures=0. If you also extract the free Lite edition next to the paid folder (as lite/), the runner also compares the shared files and the count is 110.
  • In your own project: copy addons/inventory_save_lite into res://addons, and addons/inventory_save_adapter if you want the bridge. The bridge preloads the core from res://addons/inventory_save_lite/, so keep that path. The editor plugins in both folders do nothing; you do not need to enable them.
const InventoryData = preload("res://addons/inventory_save_lite/inventory_data.gd")
const InventoryCodec = preload("res://addons/inventory_save_lite/inventory_codec.gd")
const InventoryFileStore = preload("res://addons/inventory_save_lite/inventory_file_store.gd")
const SaveKitInventoryBridge = preload("res://addons/inventory_save_adapter/savekit_inventory_bridge.gd")

var codec := InventoryCodec.new()
var model := InventoryData.new()
model.replace_containers([{"id": "bag", "capacity": 8, "slots": [{"index": 0, "item_id": "potion", "count": 2, "x": 0, "y": 0}]}])

# Standalone file
var store := InventoryFileStore.new()
var err := store.write("user://inventory.json", model, codec)  # returns an Error
var loaded := InventoryData.new()
var result := store.read("user://inventory.json", loaded, codec)  # {error, data, warnings, recovered}

# Through a save manager that has save_slot / load_slot
var bridge := SaveKitInventoryBridge.new()
bridge.configure(your_save_manager, codec)  # returns an Error
bridge.save_inventory("slot_1", model, 12.5)  # returns an Error
var back := bridge.load_inventory("slot_1", loaded)  # {error, data, warnings, recovered}

What was tested

Build v1.0.2, Godot 4.7.2.stable.official.ed1daf0bf, macOS, headless only, on fresh extractions of the final zip.

  • The included test runner: 76 checks, 0 failures standalone, and 110 checks, 0 failures with the free Lite edition extracted beside it. The Lite edition's own runner: 61 checks, 0 failures.
  • The demo round trip prints PASS demo/round_trip (run from the Lite layout, the paid standalone layout and the paid + Lite layout).
  • The core files in this download are byte-identical to the free Lite edition's.
  • Extra checks that are not part of the download: 176 corruption and edge-case checks on the core (truncated, empty, wrong-type and oversized files, bad counts, unknown items, version chains, backup fallback) gave 174 passes and 2 fails, with the same result in all three layouts; the two fails are listed in "Known limitations". A further 38 checks on the bridge all passed: 28 against a stub save manager and 10 against the real GodotSaveKit v1.0.0 save manager (save, load round trip including x/y, a second save, a corrupt main file recovered from the manager's backup, and a newer envelope version refused). The same 38 checks also passed against GodotSaveKit v1.0.1.
  • The code sample above ran on an earlier build (v1.0.1): the file-store part and the bridge part (against the stub) returned no errors and the loaded data equalled the saved data. v1.0.2 does not change the add-on code the sample calls, and the sample was not re-run on v1.0.2.

What was not tested

  • Windows, Linux, any Godot version other than 4.7.2, exported games, and using the add-on by hand in the editor GUI (only headless project import and script runs were done).
  • Any third-party inventory plugin. The mapping example handles plain {position, id, quantity} records only; no plugin compatibility is claimed. GodotSaveKit was tested only at v1.0.0 and v1.0.1.
  • Power loss during a save, a migration callback that throws an error, and performance beyond one round trip of 65,536 slots.

Please test on your own setup before you rely on it.

Known limitations

  • save_inventory replaces the whole slot. It sends {inventory: snapshot} as the entire payload of that slot, so any other game data stored in the same slot is lost. Use a slot only for the inventory, or build your own payload (recipe guide). There is no merging.
  • The tests inside the download use a stub. The run against the real GodotSaveKit came from a check script that is not in the download.
  • InventoryFileStore.write can overwrite a file saved by a newer schema without keeping a backup of it. read refuses such a file; write does not. This only matters if you downgrade the library, and there is no newer schema today.
  • read with an allow-list can quietly return the older .bak. If the main file is valid JSON but holds item IDs that are not in your list (and you did not pass skip_unknown), read returns the previous backup with recovered = true and no warning. Always check recovered. Separately, a schema_version above 2,147,483,647 gives ERR_INVALID_DATA (and can fall back to the backup) instead of ERR_UNAVAILABLE.
  • Stack limits are enforced when reading and in snapshot(), not in write or to_json. An over-limit stack is written and rejected on the next read that passes stack_limits.
  • There is no integrity check. Files are not encrypted and have no checksum. A file with invalid UTF-8 bytes inside a string value loads without an error, and Godot replaces the bytes with U+FFFD characters (a mangled container ID, for example). This is not tamper protection.
  • A hand-built Dictionary that mixes the integer 1 and the float 1.0 as slot indexes is accepted by restore() and ends up with two items on one slot. Saving that model is refused with ERR_INVALID_DATA, so no bad file is written. JSON input cannot produce this case.
  • The add-on declares six global class names: InventoryCodec, InventoryData, InventoryFileStore, InventoryMigrations, InventoryValidator and SaveKitInventoryBridge. They could clash with scripts in your project.
  • Cosmetic: the root project.godot is named "Inventory Save Adapter Lite Tests" and enables the Lite plugin, not the adapter plugin. Importing the root project prints a harmless warning that it found another project.godot in demo/.
  • No inventory UI, autosave, save-slot management, encryption, crash-durability guarantee or third-party plugin certification.

Licence

Copyright (c) 2026 Fortress MSSP LLC. This is a summary; the licence files in the download are the governing text, and this summary is not legal advice. LICENCE.md lists the licence of every file.

  • MIT: the persistence core (addons/inventory_save_lite/), the demo, the tests run_all.gd, test_codec.gd, test_files.gd, test_migrations.gd and test_validation.gd, and the root documentation and project files. The free Lite edition has the same core under the same MIT licence.
  • Paid-only, single-developer commercial licence (LICENSE-PAID.txt), 10 files: the bridge (addons/inventory_save_adapter/, 3 files), docs/recipe-guide.md, examples/ (3 files), tests/run_paid.gd, tests/test_savekit_bridge.gd and tests/test_recipes.gd. LICENSE-PAID.txt is the licence text itself and lists these 10 paths.
  • What the paid licence allows: one named developer (the individual who bought it) may use the 10 files, modify them, and include them in any number of games and projects, including games that earn revenue. Including the scripts in a finished game you release or operate is permitted.
  • What it does not allow: reselling, redistributing, sublicensing, renting, lending or giving away the 10 files' source code, original or modified, alone or inside another kit, template, asset pack or plugin; sharing the source with anyone who has no licence of their own, or posting it in a public repository or marketplace listing; removing the copyright notice; claiming to be the author. Each additional developer who needs the source needs their own licence. The licence is non-transferable.
  • The files are provided as is, without warranty. Please read LICENSE-PAID.txt before you buy if more than one person will work with the source.

AI disclosure

The code and the documentation text were written with AI assistance and then tested as described above. The images on this page are not AI-generated.

Related

Purchase

Get this asset pack and 11 more for $59.93 USD
View bundle
Buy Now
On Sale!
40% Off
$9.99 $5.99 USD or more

In order to download this asset pack you must purchase it at or above the minimum price of $5.99 USD. You will get access to the following files:

InventorySaveAdapter-v1.0.2.zip 28 kB

Leave a comment

Log in with itch.io to leave a comment.