fix(server): restore earned quest costume before validating upgrades
This commit is contained in:
+13
-11
@@ -440,7 +440,19 @@ func serve(args []string) (serveErr error) {
|
||||
if err := ownedEquipment.AttachOptionReroll(equipmentOptionReroll, wallet, ownedItems); err != nil {
|
||||
return fmt.Errorf("attach equipment option reroll GameData: %w", err)
|
||||
}
|
||||
collection, err := player.OpenCollectionStore(stateRepository, starter.Costumes)
|
||||
worldService, err := world.Load(filepath.Clean(*worldSeed), gameData, *gameDataVersion,
|
||||
stateRepository, progressState, starter, ownedEquipment, ownedItems, wallet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load world state: %w", err)
|
||||
}
|
||||
// Restore all earned seed ownership before validating persisted upgrades.
|
||||
// A quest costume is not a collection entry; attaching it after opening
|
||||
// collection would reject its otherwise valid burst ledger on restart.
|
||||
baseCostumes := append([]player.Costume(nil), starter.Costumes...)
|
||||
if reward, earned := worldService.EarnedQuestCostume(); earned {
|
||||
baseCostumes = append(baseCostumes, reward)
|
||||
}
|
||||
collection, err := player.OpenCollectionStore(stateRepository, baseCostumes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load owned collection: %w", err)
|
||||
}
|
||||
@@ -478,22 +490,12 @@ func serve(args []string) (serveErr error) {
|
||||
gachaService.AttachPreviewMission(func() error {
|
||||
return missionService.CompleteMission(gamedata.MissionKey{GroupType: 0, GroupID: 1, ID: 111})
|
||||
})
|
||||
worldService, err := world.Load(filepath.Clean(*worldSeed), gameData, *gameDataVersion,
|
||||
stateRepository, progressState, starter, ownedEquipment, ownedItems, wallet)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load world state: %w", err)
|
||||
}
|
||||
if err := collection.BindBaseCharacters(worldService.CharacterService().RawAll()); err != nil {
|
||||
return fmt.Errorf("bind base collection characters: %w", err)
|
||||
}
|
||||
if err := mailService.AttachCostumeRewards(collection, limitedCostumes); err != nil {
|
||||
return fmt.Errorf("attach limited costume mail rewards: %w", err)
|
||||
}
|
||||
if reward, earned := worldService.EarnedQuestCostume(); earned {
|
||||
if err := collection.AttachRewardCostume(reward); err != nil {
|
||||
return fmt.Errorf("attach earned quest costume: %w", err)
|
||||
}
|
||||
}
|
||||
if err := worldService.AttachCollection(collection); err != nil {
|
||||
return fmt.Errorf("attach gacha collection state: %w", err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package player
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"bd2server/internal/server/stateio"
|
||||
"bd2server/internal/server/wire"
|
||||
)
|
||||
|
||||
func TestEarnedQuestCostumeMustBeRestoredBeforeBurstValidation(t *testing.T) {
|
||||
store := stateio.NewMemory()
|
||||
base := []Costume{{InvenIndex: 88, ID: 900}}
|
||||
reward := Costume{InvenIndex: 99, ID: 4202, UseChar: 77}
|
||||
collection, err := OpenCollectionStore(store, base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := collection.EnsurePersisted(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := collection.AttachRewardCostume(reward); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
record := CostumeBurstUpgradeRecord{CostumeID: reward.ID, Level: 1, Digest: strings.Repeat("a", 64), Code: 578, Body: wire.AppendVarint(nil, 1, 1)}
|
||||
if err := collection.ApplyCostumeBurst(reward.InvenIndex, 0, 1, record); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := OpenCollectionStore(store, base); err == nil {
|
||||
t.Fatal("accepted burst ledger with incomplete restored ownership")
|
||||
}
|
||||
reloaded, err := OpenCollectionStore(store, append(base, reward))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, owned := reloaded.CostumeByID(reward.ID)
|
||||
if !owned || got.InvenIndex != reward.InvenIndex || got.BurstLevel != 1 {
|
||||
t.Fatalf("restored reward costume=%+v owned=%v", got, owned)
|
||||
}
|
||||
if got, found := reloaded.CostumeBurstReplay(reward.InvenIndex, 1); !found || got.Digest != record.Digest {
|
||||
t.Fatal("restart lost burst upgrade replay")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user