preserve ID order when persisting to JSON to prevent git churn

This commit is contained in:
Sky Johnson 2025-08-14 12:17:05 -05:00
parent 7b99ffc02c
commit adcaa609a6
5 changed files with 1996 additions and 1988 deletions

View File

@ -7,25 +7,39 @@
"att": "maxhp,10"
},
{
"id": 32,
"name": "Fortune Drop",
"level": 5,
"id": 2,
"name": "Life Stone",
"level": 10,
"type": 1,
"att": "goldbonus,10"
"att": "maxhp,25"
},
{
"id": 28,
"name": "Topaz",
"level": 50,
"id": 3,
"name": "Life Rock",
"level": 25,
"type": 1,
"att": "dexterity,150"
"att": "maxhp,50"
},
{
"id": 26,
"name": "Pearl",
"level": 50,
"id": 4,
"name": "Magic Pebble",
"level": 1,
"type": 1,
"att": "maxmp,150"
"att": "maxmp,10"
},
{
"id": 5,
"name": "Magic Stone",
"level": 10,
"type": 1,
"att": "maxmp,25"
},
{
"id": 6,
"name": "Magic Rock",
"level": 25,
"type": 1,
"att": "maxmp,50"
},
{
"id": 7,
@ -34,6 +48,20 @@
"type": 1,
"att": "defensepower,25"
},
{
"id": 8,
"name": "Dragon's Plate",
"level": 30,
"type": 1,
"att": "defensepower,50"
},
{
"id": 9,
"name": "Dragon's Claw",
"level": 10,
"type": 1,
"att": "attackpower,25"
},
{
"id": 10,
"name": "Dragon's Tooth",
@ -42,11 +70,60 @@
"att": "attackpower,50"
},
{
"id": 6,
"name": "Magic Rock",
"id": 11,
"name": "Dragon's Tear",
"level": 35,
"type": 1,
"att": "strength,50"
},
{
"id": 12,
"name": "Dragon's Wing",
"level": 35,
"type": 1,
"att": "dexterity,50"
},
{
"id": 13,
"name": "Demon's Sin",
"level": 35,
"type": 1,
"att": "maxhp,-50,strength,50"
},
{
"id": 14,
"name": "Demon's Fall",
"level": 35,
"type": 1,
"att": "maxmp,-50,strength,50"
},
{
"id": 15,
"name": "Demon's Lie",
"level": 45,
"type": 1,
"att": "maxhp,-100,strength,100"
},
{
"id": 16,
"name": "Demon's Hate",
"level": 45,
"type": 1,
"att": "maxmp,-100,strength,100"
},
{
"id": 17,
"name": "Angel's Joy",
"level": 25,
"type": 1,
"att": "maxmp,50"
"att": "maxhp,25,strength,25"
},
{
"id": 18,
"name": "Angel's Rise",
"level": 30,
"type": 1,
"att": "maxhp,50,strength,50"
},
{
"id": 19,
@ -62,13 +139,6 @@
"type": 1,
"att": "maxhp,100,strength,100"
},
{
"id": 8,
"name": "Dragon's Plate",
"level": 30,
"type": 1,
"att": "defensepower,50"
},
{
"id": 21,
"name": "Seraph's Joy",
@ -77,130 +147,11 @@
"att": "maxmp,25,dexterity,25"
},
{
"id": 24,
"name": "Seraph's Love",
"level": 40,
"type": 1,
"att": "maxmp,100,dexterity,100"
},
{
"id": 18,
"name": "Angel's Rise",
"id": 22,
"name": "Seraph's Rise",
"level": 30,
"type": 1,
"att": "maxhp,50,strength,50"
},
{
"id": 12,
"name": "Dragon's Wing",
"level": 35,
"type": 1,
"att": "dexterity,50"
},
{
"id": 15,
"name": "Demon's Lie",
"level": 45,
"type": 1,
"att": "maxhp,-100,strength,100"
},
{
"id": 11,
"name": "Dragon's Tear",
"level": 35,
"type": 1,
"att": "strength,50"
},
{
"id": 5,
"name": "Magic Stone",
"level": 10,
"type": 1,
"att": "maxmp,25"
},
{
"id": 14,
"name": "Demon's Fall",
"level": 35,
"type": 1,
"att": "maxmp,-50,strength,50"
},
{
"id": 29,
"name": "Obsidian",
"level": 50,
"type": 1,
"att": "attackpower,150"
},
{
"id": 17,
"name": "Angel's Joy",
"level": 25,
"type": 1,
"att": "maxhp,25,strength,25"
},
{
"id": 27,
"name": "Emerald",
"level": 50,
"type": 1,
"att": "strength,150"
},
{
"id": 13,
"name": "Demon's Sin",
"level": 35,
"type": 1,
"att": "maxhp,-50,strength,50"
},
{
"id": 9,
"name": "Dragon's Claw",
"level": 10,
"type": 1,
"att": "attackpower,25"
},
{
"id": 31,
"name": "Memory Drop",
"level": 5,
"type": 1,
"att": "expbonus,10"
},
{
"id": 4,
"name": "Magic Pebble",
"level": 1,
"type": 1,
"att": "maxmp,10"
},
{
"id": 2,
"name": "Life Stone",
"level": 10,
"type": 1,
"att": "maxhp,25"
},
{
"id": 25,
"name": "Ruby",
"level": 50,
"type": 1,
"att": "maxhp,150"
},
{
"id": 30,
"name": "Diamond",
"level": 50,
"type": 1,
"att": "defensepower,150"
},
{
"id": 3,
"name": "Life Rock",
"level": 25,
"type": 1,
"att": "maxhp,50"
"att": "maxmp,50,dexterity,50"
},
{
"id": 23,
@ -210,17 +161,66 @@
"att": "maxmp,75,dexterity,75"
},
{
"id": 16,
"name": "Demon's Hate",
"level": 45,
"id": 24,
"name": "Seraph's Love",
"level": 40,
"type": 1,
"att": "maxmp,-100,strength,100"
"att": "maxmp,100,dexterity,100"
},
{
"id": 22,
"name": "Seraph's Rise",
"level": 30,
"id": 25,
"name": "Ruby",
"level": 50,
"type": 1,
"att": "maxmp,50,dexterity,50"
"att": "maxhp,150"
},
{
"id": 26,
"name": "Pearl",
"level": 50,
"type": 1,
"att": "maxmp,150"
},
{
"id": 27,
"name": "Emerald",
"level": 50,
"type": 1,
"att": "strength,150"
},
{
"id": 28,
"name": "Topaz",
"level": 50,
"type": 1,
"att": "dexterity,150"
},
{
"id": 29,
"name": "Obsidian",
"level": 50,
"type": 1,
"att": "attackpower,150"
},
{
"id": 30,
"name": "Diamond",
"level": 50,
"type": 1,
"att": "defensepower,150"
},
{
"id": 31,
"name": "Memory Drop",
"level": 5,
"type": 1,
"att": "expbonus,10"
},
{
"id": 32,
"name": "Fortune Drop",
"level": 5,
"type": 1,
"att": "goldbonus,10"
}
]

View File

@ -1,4 +1,76 @@
[
{
"id": 1,
"type": 1,
"name": "Stick",
"value": 10,
"att": 2,
"special": ""
},
{
"id": 2,
"type": 1,
"name": "Branch",
"value": 30,
"att": 4,
"special": ""
},
{
"id": 3,
"type": 1,
"name": "Club",
"value": 40,
"att": 5,
"special": ""
},
{
"id": 4,
"type": 1,
"name": "Dagger",
"value": 90,
"att": 8,
"special": ""
},
{
"id": 5,
"type": 1,
"name": "Hatchet",
"value": 150,
"att": 12,
"special": ""
},
{
"id": 6,
"type": 1,
"name": "Axe",
"value": 200,
"att": 16,
"special": ""
},
{
"id": 7,
"type": 1,
"name": "Brand",
"value": 300,
"att": 25,
"special": ""
},
{
"id": 8,
"type": 1,
"name": "Poleaxe",
"value": 500,
"att": 35,
"special": ""
},
{
"id": 9,
"type": 1,
"name": "Broadsword",
"value": 800,
"att": 45,
"special": ""
},
{
"id": 10,
"type": 1,
@ -7,6 +79,46 @@
"att": 50,
"special": ""
},
{
"id": 11,
"type": 1,
"name": "Claymore",
"value": 2000,
"att": 60,
"special": ""
},
{
"id": 12,
"type": 1,
"name": "Dark Axe",
"value": 3000,
"att": 100,
"special": "expbonus,-5"
},
{
"id": 13,
"type": 1,
"name": "Dark Sword",
"value": 4500,
"att": 125,
"special": "expbonus,-10"
},
{
"id": 14,
"type": 1,
"name": "Bright Sword",
"value": 6000,
"att": 100,
"special": "expbonus,10"
},
{
"id": 15,
"type": 1,
"name": "Magic Sword",
"value": 10000,
"att": 150,
"special": "maxmp,50"
},
{
"id": 16,
"type": 1,
@ -16,19 +128,19 @@
"special": "strength,50"
},
{
"id": 26,
"id": 17,
"type": 2,
"name": "Bright Armor",
"value": 10000,
"att": 175,
"special": "expbonus,10"
"name": "Skivvies",
"value": 25,
"att": 2,
"special": "goldbonus,10"
},
{
"id": 7,
"type": 1,
"name": "Brand",
"value": 300,
"att": 25,
"id": 18,
"type": 2,
"name": "Clothes",
"value": 50,
"att": 5,
"special": ""
},
{
@ -40,19 +152,35 @@
"special": ""
},
{
"id": 13,
"type": 1,
"name": "Dark Sword",
"value": 4500,
"att": 125,
"special": "expbonus,-10"
"id": 20,
"type": 2,
"name": "Hard Leather Armor",
"value": 150,
"att": 25,
"special": ""
},
{
"id": 3,
"type": 1,
"name": "Club",
"value": 40,
"att": 5,
"id": 21,
"type": 2,
"name": "Chain Mail",
"value": 300,
"att": 30,
"special": ""
},
{
"id": 22,
"type": 2,
"name": "Bronze Plate",
"value": 900,
"att": 50,
"special": ""
},
{
"id": 23,
"type": 2,
"name": "Iron Plate",
"value": 2000,
"att": 100,
"special": ""
},
{
@ -64,19 +192,43 @@
"special": "maxmp,50"
},
{
"id": 21,
"id": 25,
"type": 2,
"name": "Chain Mail",
"value": 300,
"att": 30,
"name": "Dark Armor",
"value": 5000,
"att": 150,
"special": "expbonus,-10"
},
{
"id": 26,
"type": 2,
"name": "Bright Armor",
"value": 10000,
"att": 175,
"special": "expbonus,10"
},
{
"id": 27,
"type": 2,
"name": "Destiny Raiment",
"value": 50000,
"att": 200,
"special": "dexterity,50"
},
{
"id": 28,
"type": 3,
"name": "Reed Shield",
"value": 50,
"att": 2,
"special": ""
},
{
"id": 1,
"type": 1,
"name": "Stick",
"value": 10,
"att": 2,
"id": 29,
"type": 3,
"name": "Buckler",
"value": 100,
"att": 4,
"special": ""
},
{
@ -95,150 +247,6 @@
"att": 30,
"special": ""
},
{
"id": 4,
"type": 1,
"name": "Dagger",
"value": 90,
"att": 8,
"special": ""
},
{
"id": 8,
"type": 1,
"name": "Poleaxe",
"value": 500,
"att": 35,
"special": ""
},
{
"id": 5,
"type": 1,
"name": "Hatchet",
"value": 150,
"att": 12,
"special": ""
},
{
"id": 22,
"type": 2,
"name": "Bronze Plate",
"value": 900,
"att": 50,
"special": ""
},
{
"id": 17,
"type": 2,
"name": "Skivvies",
"value": 25,
"att": 2,
"special": "goldbonus,10"
},
{
"id": 27,
"type": 2,
"name": "Destiny Raiment",
"value": 50000,
"att": 200,
"special": "dexterity,50"
},
{
"id": 15,
"type": 1,
"name": "Magic Sword",
"value": 10000,
"att": 150,
"special": "maxmp,50"
},
{
"id": 9,
"type": 1,
"name": "Broadsword",
"value": 800,
"att": 45,
"special": ""
},
{
"id": 29,
"type": 3,
"name": "Buckler",
"value": 100,
"att": 4,
"special": ""
},
{
"id": 12,
"type": 1,
"name": "Dark Axe",
"value": 3000,
"att": 100,
"special": "expbonus,-5"
},
{
"id": 33,
"type": 3,
"name": "Destiny Aegis",
"value": 25000,
"att": 100,
"special": "maxhp,50"
},
{
"id": 6,
"type": 1,
"name": "Axe",
"value": 200,
"att": 16,
"special": ""
},
{
"id": 20,
"type": 2,
"name": "Hard Leather Armor",
"value": 150,
"att": 25,
"special": ""
},
{
"id": 11,
"type": 1,
"name": "Claymore",
"value": 2000,
"att": 60,
"special": ""
},
{
"id": 2,
"type": 1,
"name": "Branch",
"value": 30,
"att": 4,
"special": ""
},
{
"id": 25,
"type": 2,
"name": "Dark Armor",
"value": 5000,
"att": 150,
"special": "expbonus,-10"
},
{
"id": 14,
"type": 1,
"name": "Bright Sword",
"value": 6000,
"att": 100,
"special": "expbonus,10"
},
{
"id": 23,
"type": 2,
"name": "Iron Plate",
"value": 2000,
"att": 100,
"special": ""
},
{
"id": 32,
"type": 3,
@ -248,19 +256,11 @@
"special": ""
},
{
"id": 28,
"id": 33,
"type": 3,
"name": "Reed Shield",
"value": 50,
"att": 2,
"special": ""
},
{
"id": 18,
"type": 2,
"name": "Clothes",
"value": 50,
"att": 5,
"special": ""
"name": "Destiny Aegis",
"value": 25000,
"att": 100,
"special": "maxhp,50"
}
]

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,4 @@
[
{
"id": 4,
"name": "Breath",
"mp": 50,
"attribute": 100,
"type": 1
},
{
"id": 14,
"name": "Craze",
"mp": 10,
"attribute": 10,
"type": 4
},
{
"id": 18,
"name": "Fend",
"mp": 20,
"attribute": 25,
"type": 5
},
{
"id": 5,
"name": "Gaia",
"mp": 75,
"attribute": 150,
"type": 1
},
{
"id": 10,
"name": "Chaos",
"mp": 50,
"attribute": 130,
"type": 2
},
{
"id": 6,
"name": "Hurt",
"mp": 5,
"attribute": 15,
"type": 2
},
{
"id": 3,
"name": "Life",
"mp": 25,
"attribute": 50,
"type": 1
},
{
"id": 8,
"name": "Maim",
"mp": 25,
"attribute": 70,
"type": 2
},
{
"id": 15,
"name": "Rage",
"mp": 20,
"attribute": 25,
"type": 4
},
{
"id": 19,
"name": "Barrier",
"mp": 30,
"attribute": 50,
"type": 5
},
{
"id": 1,
"name": "Heal",
@ -76,41 +6,6 @@
"attribute": 10,
"type": 1
},
{
"id": 12,
"name": "Dream",
"mp": 30,
"attribute": 9,
"type": 3
},
{
"id": 7,
"name": "Pain",
"mp": 12,
"attribute": 35,
"type": 2
},
{
"id": 17,
"name": "Ward",
"mp": 10,
"attribute": 10,
"type": 5
},
{
"id": 9,
"name": "Rend",
"mp": 40,
"attribute": 100,
"type": 2
},
{
"id": 13,
"name": "Nightmare",
"mp": 60,
"attribute": 13,
"type": 3
},
{
"id": 2,
"name": "Revive",
@ -118,6 +13,62 @@
"attribute": 25,
"type": 1
},
{
"id": 3,
"name": "Life",
"mp": 25,
"attribute": 50,
"type": 1
},
{
"id": 4,
"name": "Breath",
"mp": 50,
"attribute": 100,
"type": 1
},
{
"id": 5,
"name": "Gaia",
"mp": 75,
"attribute": 150,
"type": 1
},
{
"id": 6,
"name": "Hurt",
"mp": 5,
"attribute": 15,
"type": 2
},
{
"id": 7,
"name": "Pain",
"mp": 12,
"attribute": 35,
"type": 2
},
{
"id": 8,
"name": "Maim",
"mp": 25,
"attribute": 70,
"type": 2
},
{
"id": 9,
"name": "Rend",
"mp": 40,
"attribute": 100,
"type": 2
},
{
"id": 10,
"name": "Chaos",
"mp": 50,
"attribute": 130,
"type": 2
},
{
"id": 11,
"name": "Sleep",
@ -125,11 +76,60 @@
"attribute": 5,
"type": 3
},
{
"id": 12,
"name": "Dream",
"mp": 30,
"attribute": 9,
"type": 3
},
{
"id": 13,
"name": "Nightmare",
"mp": 60,
"attribute": 13,
"type": 3
},
{
"id": 14,
"name": "Craze",
"mp": 10,
"attribute": 10,
"type": 4
},
{
"id": 15,
"name": "Rage",
"mp": 20,
"attribute": 25,
"type": 4
},
{
"id": 16,
"name": "Fury",
"mp": 30,
"attribute": 50,
"type": 4
},
{
"id": 17,
"name": "Ward",
"mp": 10,
"attribute": 10,
"type": 5
},
{
"id": 18,
"name": "Fend",
"mp": 20,
"attribute": 25,
"type": 5
},
{
"id": 19,
"name": "Barrier",
"mp": 30,
"attribute": 50,
"type": 5
}
]

View File

@ -420,14 +420,22 @@ func (bs *BaseStore[T]) LoadFromJSON(filename string) error {
return nil
}
// SaveToJSON saves items to JSON atomically
// SaveToJSON saves items to JSON atomically with consistent ID ordering
func (bs *BaseStore[T]) SaveToJSON(filename string) error {
bs.mu.RLock()
defer bs.mu.RUnlock()
// Get sorted IDs for consistent ordering
ids := make([]int, 0, len(bs.items))
for id := range bs.items {
ids = append(ids, id)
}
sort.Ints(ids)
// Build items slice in ID order
items := make([]*T, 0, len(bs.items))
for _, item := range bs.items {
items = append(items, item)
for _, id := range ids {
items = append(items, bs.items[id])
}
data, err := json.MarshalIndent(items, "", "\t")