pre cw with probe and a bunch script to read game behavior
This commit is contained in:
1 parent
5120219ae2
commit
da8a32f60d
310 files changed
+219693
-872
No files matched your search
@@ -0,0 +1,175 @@
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gac-hkrpg-go/internal/common"
|
||||
goproto "gac-hkrpg-go/protocol/proto"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestLightconeSwapAndUnequipPersistAssignments(t *testing.T) {
|
||||
t.Chdir(t.TempDir())
|
||||
writeEquipmentFixture(t, `{"lightcones":[{"item_id":23001,"internal_uid":1,"equip_avatar":1201},{"item_id":23002,"internal_uid":2,"equip_avatar":1202}],"relics":[]}`)
|
||||
|
||||
player := &common.FreesrData{
|
||||
Avatars: map[uint32]*common.AvatarJson{
|
||||
1201: {AvatarID: 1201},
|
||||
1202: {AvatarID: 1202},
|
||||
},
|
||||
Lightcones: []common.Lightcone{
|
||||
{ItemID: 23001, InternalUID: 1, EquipAvatar: 1201},
|
||||
{ItemID: 23002, InternalUID: 2, EquipAvatar: 1202},
|
||||
},
|
||||
}
|
||||
session := &Session{json: player}
|
||||
|
||||
update, err := setLightconeEquipper(session, 1201, 3002)
|
||||
if err != nil {
|
||||
t.Fatalf("equip Light Cone: %v", err)
|
||||
}
|
||||
if player.Lightcones[0].EquipAvatar != 1202 || player.Lightcones[1].EquipAvatar != 1201 {
|
||||
t.Fatalf("Light Cone swap failed: %+v", player.Lightcones)
|
||||
}
|
||||
if len(update.EquipmentList) != 2 || len(update.AvatarSync.AvatarList) != 2 {
|
||||
t.Fatalf("swap did not sync both Light Cones and avatars: %+v", update)
|
||||
}
|
||||
assertSavedEquipmentOwners(t, "lightcones", map[uint32]uint32{1: 1202, 2: 1201})
|
||||
|
||||
update, err = setLightconeEquipper(session, 1201, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("unequip Light Cone: %v", err)
|
||||
}
|
||||
if player.Lightcones[1].EquipAvatar != 0 || len(update.EquipmentList) != 1 {
|
||||
t.Fatalf("Light Cone unequip failed: items=%+v update=%+v", player.Lightcones, update)
|
||||
}
|
||||
assertSavedEquipmentOwners(t, "lightcones", map[uint32]uint32{1: 1202, 2: 0})
|
||||
}
|
||||
|
||||
func TestRelicSwapUnequipAndSlotValidationPersistAssignments(t *testing.T) {
|
||||
t.Chdir(t.TempDir())
|
||||
writeEquipmentFixture(t, `{"lightcones":[],"relics":[{"relic_id":31012,"internal_uid":11,"equip_avatar":1201},{"relic_id":32012,"internal_uid":12,"equip_avatar":1202}]}`)
|
||||
|
||||
player := &common.FreesrData{
|
||||
Avatars: map[uint32]*common.AvatarJson{
|
||||
1201: {AvatarID: 1201},
|
||||
1202: {AvatarID: 1202},
|
||||
},
|
||||
Relics: []common.Relic{
|
||||
{RelicID: 31012, InternalUID: 11, EquipAvatar: 1201},
|
||||
{RelicID: 32012, InternalUID: 12, EquipAvatar: 1202},
|
||||
},
|
||||
}
|
||||
session := &Session{json: player}
|
||||
|
||||
wrongSlot, err := equipRelic(session, &goproto.DressRelicAvatarCsReq{
|
||||
AvatarId: 1201,
|
||||
SwitchList: []*goproto.DressRelicParam{{RelicType: 1, RelicUniqueId: 12}},
|
||||
})
|
||||
if err != nil || wrongSlot != nil {
|
||||
t.Fatalf("mismatched Relic slot should be ignored: update=%+v err=%v", wrongSlot, err)
|
||||
}
|
||||
if player.Relics[0].EquipAvatar != 1201 || player.Relics[1].EquipAvatar != 1202 {
|
||||
t.Fatalf("mismatched Relic slot changed ownership: %+v", player.Relics)
|
||||
}
|
||||
|
||||
update, err := equipRelic(session, &goproto.DressRelicAvatarCsReq{
|
||||
AvatarId: 1201,
|
||||
SwitchList: []*goproto.DressRelicParam{{RelicType: 2, RelicUniqueId: 12}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("equip Relic: %v", err)
|
||||
}
|
||||
if player.Relics[0].EquipAvatar != 1202 || player.Relics[1].EquipAvatar != 1201 {
|
||||
t.Fatalf("Relic swap failed: %+v", player.Relics)
|
||||
}
|
||||
if len(update.RelicList) != 2 || len(update.AvatarSync.AvatarList) != 2 {
|
||||
t.Fatalf("swap did not sync both Relics and avatars: %+v", update)
|
||||
}
|
||||
assertSavedEquipmentOwners(t, "relics", map[uint32]uint32{11: 1202, 12: 1201})
|
||||
|
||||
update, err = unequipRelic(session, &goproto.TakeOffRelicCsReq{
|
||||
AvatarId: 1201,
|
||||
RelicTypeList: []uint32{2},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unequip Relic: %v", err)
|
||||
}
|
||||
if player.Relics[1].EquipAvatar != 0 || len(update.RelicList) != 1 {
|
||||
t.Fatalf("Relic unequip failed: items=%+v update=%+v", player.Relics, update)
|
||||
}
|
||||
assertSavedEquipmentOwners(t, "relics", map[uint32]uint32{11: 1202, 12: 0})
|
||||
}
|
||||
|
||||
func TestEquipmentPickerAuxiliaryRequestsHaveTypedReplies(t *testing.T) {
|
||||
for _, name := range []string{
|
||||
"RelicPresetGetPlanCsReq",
|
||||
"RelicSmartWearGetPlanCsReq",
|
||||
"RelicSmartWearGetPinRelicCsReq",
|
||||
"GetBigDataRecommendCsReq",
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
id, ok := goproto.CmdIDByName[name]
|
||||
if !ok {
|
||||
t.Fatalf("protocol table is missing %s", name)
|
||||
}
|
||||
if typedHandlers[uint16(id)] == nil {
|
||||
t.Fatalf("%s is not registered as a typed handler", name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
avatarID := uint32(1201)
|
||||
recommendation := emptyEquipmentRecommendation(avatarID, goproto.BigDataRecommendType_BIG_DATA_RECOMMEND_TYPE_AVATAR_RELIC)
|
||||
responses := []proto.Message{
|
||||
emptyRelicPresetPlans(avatarID),
|
||||
emptyRelicSmartWearPlans(avatarID),
|
||||
emptyPinnedRelics(avatarID),
|
||||
&recommendation,
|
||||
}
|
||||
for _, response := range responses {
|
||||
encoded, err := proto.Marshal(response)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal %T: %v", response, err)
|
||||
}
|
||||
if len(encoded) == 0 {
|
||||
t.Fatalf("%T encoded as an empty response", response)
|
||||
}
|
||||
}
|
||||
if recommendation.EquipAvatar != avatarID || recommendation.BigDataRecommendType != goproto.BigDataRecommendType_BIG_DATA_RECOMMEND_TYPE_AVATAR_RELIC {
|
||||
t.Fatalf("recommendation response lost request context: %+v", recommendation)
|
||||
}
|
||||
}
|
||||
|
||||
func writeEquipmentFixture(t *testing.T, contents string) {
|
||||
t.Helper()
|
||||
if err := os.WriteFile("freesr-data.json", []byte(contents), 0600); err != nil {
|
||||
t.Fatalf("write fixture: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func assertSavedEquipmentOwners(t *testing.T, collection string, expected map[uint32]uint32) {
|
||||
t.Helper()
|
||||
contents, err := os.ReadFile("freesr-data.json")
|
||||
if err != nil {
|
||||
t.Fatalf("read persisted equipment: %v", err)
|
||||
}
|
||||
var root map[string][]struct {
|
||||
InternalUID uint32 `json:"internal_uid"`
|
||||
EquipAvatar uint32 `json:"equip_avatar"`
|
||||
}
|
||||
if err := json.Unmarshal(contents, &root); err != nil {
|
||||
t.Fatalf("decode persisted equipment: %v", err)
|
||||
}
|
||||
owners := make(map[uint32]uint32, len(root[collection]))
|
||||
for _, entry := range root[collection] {
|
||||
owners[entry.InternalUID] = entry.EquipAvatar
|
||||
}
|
||||
for uid, want := range expected {
|
||||
if got, ok := owners[uid]; !ok || got != want {
|
||||
t.Errorf("%s UID %d owner = %d (present %v), want %d", collection, uid, got, ok, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user