A point-and-click Tk GUI for inspecting and editing
Everwind save files (Player_Local.sav,
WorldInfo.sav, and per-island world .sav files).
Warning
Always back up your save folder before using. This tool writes
directly to live save files. Bad edits can crash the game on its very
next load (see Safety notes). The editor keeps its own
per-file .bak rotation, but a manual full-folder copy is the only
thing that protects you from your own undo-stack mistakes.
- Combined view of
Player_Local.savplus every island.sav(toggle off with the Combine player + island saves checkbox). - Three tabs: Inventory, World & Islands, Character & World.
- Filter / search across item names, item ids, categories, locations, chest labels, and enchantment names.
- Toolbar toggles: Empty Items Only, Include Empty Items, User Only Items, Non-User Only, Include (loose) items.
- Group by None / Category / Location / Chest. Right-click a chest
header → Flag chest as mine ★ to keep an unanchored chest in the
"User Only" filter. Select multiple chest headers (Ctrl-click /
Shift-click) and right-click to flag or unflag them in one batch.
Flags are persisted across launches in
editor_settings.json. - Player-placed Flag Markers (map waypoints / stash flags) are
auto-detected from their
FlagMarkerDatapayload and labeled#N · Marker. They are always treated as player content (no manual ★ needed) so the User Only filter shows them by default. - Right-click any column header to hide it, then right-click any remaining header to bring hidden columns back. Hidden-column selection persists.
- Up to nine enchantment columns per row (
Ench 1…Ench 9). The full list ofECharacterStat::…modifiers attached to that physical slot is shown.
- Double-click any scalar cell to edit it in place (
SlotsWithItems,MaxStackCount,Durability,Energy,Fuel,Level,SpecialEffectLevel,Amount, or any enchantmentModifyValue). - Right-click an enchantment cell → Change enchantment type to swap
the stat. Only same-byte-length stat names are offered, because the
underlying
FStringbody needs to drop into the existing hole exactly (see How edits are safe).
| Button | What it does |
|---|---|
| Bulk apply | Write <field> = <value> on every selected row. The combo box lists every scalar field plus Ench 1–9. |
| Split stacks… | Redistribute the total quantity of an item across every slot that holds it. |
| Delete (Del) | Zero out SlotsWithItems on every selected row. |
| Repair & Top Off selected | Restore selected rows to category-appropriate defaults (full durability, max levels for gear, sane stack max for the rest). Weapons & armor (Boots / Gloves / Chestplate / Helmet) with fewer than 3 enchantments get Level 0 / SpecialEffectLevel 2 instead of 10/10. Jewelry and Tools always get 10/10. Player_Local.sav only. |
| Repair & Top Off ALL | Same rules across every populated, non-skipped slot in the loaded saves. Still scoped to Player_Local.sav by default. |
| Top Off SELECTED (incl. world) | DANGER. Bypasses the player-file scope guard. Use only on a small, hand-picked selection in a world / island save. |
| Make Max Level | Sets Level and SpecialEffectLevel = 10 on every selected weapon / tool / wearable. |
| Make Max Stacks | Sets Qty = Stack Max (and bumps Stack Max to a category-appropriate maximum) on every selected row. |
| Max Ench (25) | Sets ModifyValue = 25 on every enchantment modifier of every selected enchanted row. Skips items with no enchantments. |
| Compact empty slots… | Zeroes every scalar on slots whose SlotsWithItems is already 0, so empty slots stop showing leftover durability / level numbers from earlier items. |
| Delete all Drops | Zeros SlotsWithItems on every entry inside an unanchored "Drop · …" container (creature loot bags). Leaves chests, stations, anchored Block actors, "Loot · …" containers, and the player's own Inventory / Equipment alone. |
- Python 3.10+ with Tk (the default Windows installer bundles it).
- The core editor uses standard-library only.
- The
docs/redact_path.pyscreenshot helper needspillow(pip install pillow).
Grab EverwindSaveEditor.exe from the
Releases page
and double-click. Settings (editor_settings.json) are written next to
the .exe, so put it somewhere you have write access (a folder under
your user profile is fine — avoid Program Files).
git clone https://github.com/matziq/EverwindSaveEditor.git
cd EverwindSaveEditor
pythonw .\everwind_save_gui.py
# or just double-click run.batThe editor auto-detects the most-recent save folder under
%LOCALAPPDATA%\Everwind\Saved\SaveGames\. Use Browse Player /
Browse World to point it at a different slot.
pwsh -NoProfile -ExecutionPolicy Bypass -File .\build_exe.ps1
# -Clean wipes build/ and dist/ firstPyInstaller is installed on demand. The resulting one-file binary lands
at dist\EverwindSaveEditor.exe (~10–15 MB) and bundles item_dict.json
and item_asset_paths.json so the editor works on machines without
Python.
| Path | What it is |
|---|---|
everwind_save_gui.py |
The Tk GUI. The entry point. |
everwind_save_edit.py |
Parser + write-back library. CLI for dump / apply / set / update_meta. |
enchantments.py |
CustomModificators array decoder and per-slot grouping. |
extract_game_data.py |
One-shot generator for item_dict.json from the game's .utoc. |
harvest_save_paths.py |
Walks every loaded .sav and records the full /Game/Data/Items/... asset path for every item it sees. |
item_dict.json |
Item-id → name / category / tier lookup. Pre-generated; can be regenerated against a new game build. |
item_asset_paths.json |
item_id → /Game/Data/Items/... path map (built by harvest_save_paths.py). |
run.bat |
pythonw everwind_save_gui.py. Double-click launcher. |
build_exe.ps1 / EverwindSaveEditor.spec |
PyInstaller wrapper + spec to produce dist\EverwindSaveEditor.exe. |
tools/ |
Recovery / diagnostic helpers — see tools/README.md. |
docs/ |
README screenshots + the redaction helper used to create them. |
editor_settings.json |
Per-user runtime state. Not committed. |
The Everwind save format is a UE5 tagged-property stream with no GVAS
header. Each property is preceded by a Size field, and arrays / structs
have their own Size headers — changing a string or enum value would
ripple every enclosing size by Δlen bytes.
This editor refuses to do that. It only patches:
- Fixed-width 4-byte scalars (
IntProperty,FloatProperty) at their on-disk byte offsets. - Same-byte-length
FStringswaps for enchantment stat names (handled byapply_raw_writesineverwind_save_edit.py).
After every write, the sibling .meta CRC is rewritten — see
The .meta CRC.
Every write goes through apply_patches() / apply_raw_writes() in
everwind_save_edit.py. Before the first edit of a save file in a
session, the original is copied to a baseline backup. Every subsequent
edit creates a timestamped rotating backup. The full set you'll see in
your save folder after a few edits looks like this:
Player_Local.sav ← live (the game and the editor both write this)
Player_Local.sav.meta ← decimal-ASCII CRC32 of the live file
Player_Local.sav.backup ← game-written previous state
Player_Local.sav.backup.meta ← CRC for .backup
Player_Local.sav.bak ← editor baseline (first .bak in this session)
Player_Local.sav.bak.meta ← matching CRC, so .bak + .bak.meta is a clean restore pair
Player_Local.sav.20260608-141902.bak ← editor rotation, named <stem>.<YYYYMMDD-HHMMSS>.bak
Player_Local.sav.20260608-141955.bak
Player_Local.sav.20260608-142013.bak
…
Naming rules:
| Pattern | Created by | Cleaned up by |
|---|---|---|
<stem>.sav |
the game (and the editor on save) | never |
<stem>.sav.meta |
the editor on every write | never |
<stem>.sav.backup / .backup.meta |
the game on save | the game |
<stem>.sav.bak / .bak.meta |
the editor on the first edit of a session | never — always preserved |
<stem>.sav.<YYYYMMDD-HHMMSS>.bak |
the editor on each subsequent edit | prune_backups() when retention is set |
<stem>.sav.broken-<stamp> |
the recovery scripts in tools/, just before overwriting |
never (manual cleanup) |
Retention. The toolbar Backups field (default 5) is passed as
max_backups to every write. The unstamped <stem>.sav.bak baseline
always counts toward the budget and is never deleted. The remaining
max_backups − 1 slots are filled with the newest timestamped backups
(by mtime); older timestamped backups are deleted. Set the field to
blank for unlimited rotation.
Why .bak + .bak.meta together? The game silently reverts to
<stem>.sav.backup if a .sav body's CRC doesn't match its .meta. A
.bak without a paired .bak.meta is therefore not directly restorable
— you'd have to recompute the CRC. The editor pairs them automatically;
the recovery scripts in tools/ do the same.
"Repair & Top Off" by default touches only Player_Local.sav.
Writing MaxStackCount > 1 to a non-stacking item (most tools / weapons
/ wearables) in a world chest has caused crashes on the very next load
(EXCEPTION_STACK_OVERFLOW from the engine's pickup-spill recursion).
The escape-hatch button Top Off SELECTED (incl. world) disables the
scope guard; use it on a tiny hand-picked selection only.
Every .sav has a sibling .meta containing the decimal-ASCII CRC32
of the .sav body (no trailing newline). The game checks this on load
and silently reverts to .backup on mismatch — your edits just
vanish without any error. The editor rewrites .meta on every save; if
you patch a .sav outside the editor, call
everwind_save_edit.update_meta(path) immediately afterwards.
If you ever need to roll back, do every related file
(Player_Local.sav, WorldInfo.sav, and every island .sav) to the
same point in time. A mixed-time recovery throws
Failed to find object 'CharacterSaveData_<num>' warnings followed by
an access violation seconds after clicking Continue. The helper
scripts in tools/ (notably _rollback_proper.py and
_restore_from_backup.py) handle the bookkeeping for you and keep
.broken-<timestamp> copies of anything they overwrite.
WorldInfo.savcargo records use anAmountIntPropertyinstead ofSlotsWithItems/MaxStackCount. They're view + manual cell-edit only; the bulk Repair / Make Max actions skip them by design.- Unanchored chests in world saves (containers placed without a
BlockActor_…anchor in the file bytes) cannot be reliably distinguished from creature loot bags by the parser alone. The User Only filter therefore hides them by default. Right-click the chest header and pick Flag chest as mine ★ to keep a specific one visible — the flag persists ineditor_settings.json. - Adding brand-new item slots (rather than editing existing ones) is
not implemented. It would require a custom tree walker that updates
six nested
Sizeheaders and the front-matter type schema. The current GUI only shows the asset path and lets you copy it.
| Game version | Status |
|---|---|
| v0.4.658 | Verified compatible (2026-06-10). Save format unchanged — same property types, same INV_FIELDS, same container markers. Bundled item_dict.json (from v2026.06.01) still resolves ~95% of item ids; regenerate with extract_game_data.py for full coverage of any new items added since v2026.06.01. |
| v2026.06.01 | Verified compatible. Format unchanged; WorldInfo.sav cargo (Amount field) is read-only by design. |
| v0.4.515 | Worked. The matching item_dict.json for that version is preserved out-of-tree as a .bak. |
To regenerate item_dict.json against a new game install, run:
python .\extract_game_data.py "C:\Path\To\Everwind\skyverse\Content\Paks\skyverse-Windows.utoc"The two screenshots referenced above live in docs/. They are committed
after running docs/redact_path.py, which paints over the
Save-file Path: field so no real local username or save slot is
revealed. See docs/README.md for the workflow.
This is a personal save editor; PRs are welcome but priority is given to correctness (don't crash the game) over feature breadth. Please:
- Keep edits to same-width scalar patches unless you are also
rewriting every enclosing
Sizeheader. - Re-run on a backup save folder, launch the game, click Continue
past the main menu, and verify the world loads. The game's worst
failure mode is a quiet
.backupfallback or a crash on the next Continue click, not an obvious error in the editor.

