docs & feat: add license & attribution notice (Apache-2.0 / GPL-3.0) and core system enhancements

This commit is contained in:
CAtlas0784 committed 2026-11-01 20:14:36 +07:00
1 parent 507836d367
commit ce6aabfc55
47 files changed
+5674 -724

No files matched your search

+76 -129
View File
@@ -1,6 +1,7 @@
package gameserver
import (
"bytes"
"os"
"testing"
@@ -10,151 +11,97 @@ import (
)
func TestCurrencyWarsTalentsHandlers(t *testing.T) {
origPersistent, _ := os.ReadFile("persistent")
if origPersistent != nil {
t.Cleanup(func() {
_ = os.WriteFile("persistent", origPersistent, 0644)
})
}
session := &Session{Token: 12345}
catalog, err := common.LoadCurrencyWarsCatalog()
before, err := os.ReadFile("persistent")
if err != nil {
t.Fatalf("load catalog: %v", err)
t.Fatal(err)
}
data, rev, err := readCurrencyWarsData(catalog)
if err != nil || data == nil {
data, err = newCurrencyWarsData(catalog)
s := &Session{Token: 12345}
requests := map[string]proto.Message{
"GridFightPermanentTalentEnableCsReq": &pb.GridFightPermanentTalentEnableCsReq{CKHCLKOALKE: ^uint32(0)},
"GridFightSeasonTalentEnableCsReq": &pb.GridFightSeasonTalentEnableCsReq{CKHCLKOALKE: ^uint32(0)},
"GridFightPermanentTalentResetCsReq": &pb.GridFightPermanentTalentResetCsReq{},
"GridFightSeasonTalentResetCsReq": &pb.GridFightSeasonTalentResetCsReq{},
}
for name, req := range requests {
raw, _ := proto.Marshal(req)
if err := typedHandlers[uint16(pb.CmdIDByName[name])](s, raw); err != nil {
t.Fatal(err)
}
after, err := os.ReadFile("persistent")
if err != nil {
t.Fatalf("new data: %v", err)
t.Fatal(err)
}
rev = 0
}
session.currencyWarsRevision = rev
if err := session.saveCurrencyWarsData(data, catalog); err != nil {
t.Fatalf("save initial data: %v", err)
}
// 1. Enable Permanent Talent
permReq := &pb.GridFightPermanentTalentEnableCsReq{CKHCLKOALKE: 101}
permCmdID, ok := pb.CmdIDByName["GridFightPermanentTalentEnableCsReq"]
if !ok || typedHandlers[uint16(permCmdID)] == nil {
t.Fatal("handler GridFightPermanentTalentEnable not registered")
}
rawPerm, err := proto.Marshal(permReq)
if err != nil {
t.Fatalf("marshal permReq: %v", err)
}
if err := typedHandlers[uint16(permCmdID)](session, rawPerm); err != nil {
t.Fatalf("call GridFightPermanentTalentEnable: %v", err)
}
saved, _, err := readCurrencyWarsData(catalog)
if err != nil || saved == nil {
t.Fatalf("read saved data: %v", err)
}
if saved.LFLCDNGALME == nil || saved.LFLCDNGALME.PKELAIPIHMF == nil || saved.LFLCDNGALME.PKELAIPIHMF.MHFHLBHFIBC == nil {
t.Fatal("permanent talent container missing")
}
found := false
for _, id := range saved.LFLCDNGALME.PKELAIPIHMF.MHFHLBHFIBC.BDGMNPIJDDL {
if id == 101 {
found = true
break
if !bytes.Equal(before, after) {
t.Fatalf("unsupported talent request changed persistent: %s", name)
}
}
if !found {
t.Errorf("permanent talent 101 was not persisted: %v", saved.LFLCDNGALME.PKELAIPIHMF.MHFHLBHFIBC.BDGMNPIJDDL)
}
// 2. Enable Season Talent
seasonReq := &pb.GridFightSeasonTalentEnableCsReq{CKHCLKOALKE: 202}
seasonCmdID, ok := pb.CmdIDByName["GridFightSeasonTalentEnableCsReq"]
if !ok || typedHandlers[uint16(seasonCmdID)] == nil {
t.Fatal("handler GridFightSeasonTalentEnable not registered")
}
rawSeason, err := proto.Marshal(seasonReq)
if err != nil {
t.Fatalf("marshal seasonReq: %v", err)
}
if err := typedHandlers[uint16(seasonCmdID)](session, rawSeason); err != nil {
t.Fatalf("call GridFightSeasonTalentEnable: %v", err)
}
saved, _, _ = readCurrencyWarsData(catalog)
if saved.LFLCDNGALME == nil || saved.LFLCDNGALME.HFPEJIDDDJG == nil || saved.LFLCDNGALME.HFPEJIDDDJG.MHFHLBHFIBC == nil {
t.Fatal("season talent container missing")
}
foundSeason := false
for _, id := range saved.LFLCDNGALME.HFPEJIDDDJG.MHFHLBHFIBC.BDGMNPIJDDL {
if id == 202 {
foundSeason = true
break
}
}
if !foundSeason {
t.Errorf("season talent 202 was not persisted: %v", saved.LFLCDNGALME.HFPEJIDDDJG.MHFHLBHFIBC.BDGMNPIJDDL)
}
// 3. Reset Talents
resetCmdID, ok := pb.CmdIDByName["GridFightPermanentTalentResetCsReq"]
if ok && typedHandlers[uint16(resetCmdID)] != nil {
rawReset, _ := proto.Marshal(&pb.GridFightPermanentTalentResetCsReq{})
_ = typedHandlers[uint16(resetCmdID)](session, rawReset)
}
saved, _, _ = readCurrencyWarsData(catalog)
if len(saved.LFLCDNGALME.PKELAIPIHMF.MHFHLBHFIBC.BDGMNPIJDDL) != 0 {
t.Errorf("expected permanent talents to be empty after reset, got %v", saved.LFLCDNGALME.PKELAIPIHMF.MHFHLBHFIBC.BDGMNPIJDDL)
}
}
func TestCurrencyWarsArchiveHandlers(t *testing.T) {
record := &pb.OEDHMAHDECC{
Reason: pb.PEIJNEFOCHI_PEIJNEFOCHI_JOJPGBCECLN,
IsOverlock: false,
}
entry := cwRecordArchive(record, 2, 1)
if entry == nil || entry.BAAGDILLLME == 0 {
t.Fatal("archive record failed")
}
session := &Session{Token: 54321}
// Toggle Favour
favourReq := &pb.FavourArchiveCsReq{BAAGDILLLME: entry.BAAGDILLLME, IECKKCHJMLP: true}
favourCmdID, ok := pb.CmdIDByName["FavourArchiveCsReq"]
if !ok || typedHandlers[uint16(favourCmdID)] == nil {
t.Fatal("FavourArchive handler missing")
}
rawFavour, err := proto.Marshal(favourReq)
c, err := common.LoadCurrencyWarsCatalog()
if err != nil {
t.Fatalf("marshal favourReq: %v", err)
t.Fatal(err)
}
if err := typedHandlers[uint16(favourCmdID)](session, rawFavour); err != nil {
t.Fatalf("call FavourArchive: %v", err)
data, revision, err := readCurrencyWarsData(c)
if err != nil {
t.Fatal(err)
}
foundFavour := false
globalCWArchive.mu.RLock()
for _, e := range globalCWArchive.entries {
if e.BAAGDILLLME == entry.BAAGDILLLME && e.IECKKCHJMLP {
foundFavour = true
break
if data == nil {
data, err = newCurrencyWarsData(c)
if err != nil {
t.Fatal(err)
}
}
globalCWArchive.mu.RUnlock()
if !foundFavour {
t.Errorf("expected archive %d to be favoured", entry.BAAGDILLLME)
session := &Session{Token: 54321, currencyWarsRevision: revision}
record := &pb.OEDHMAHDECC{Reason: pb.PEIJNEFOCHI_PEIJNEFOCHI_JOJPGBCECLN}
if err := session.saveCurrencyWarsTerminal(data, c, record); err != nil {
t.Fatal(err)
}
// Get Archive
getArchiveCmdID, ok := pb.CmdIDByName["GridFightGetArchiveCsReq"]
if !ok || typedHandlers[uint16(getArchiveCmdID)] == nil {
t.Fatal("GridFightGetArchive handler missing")
snapshot, err := cwArchiveSnapshot(c)
if err != nil {
t.Fatal(err)
}
rawGetArchive, _ := proto.Marshal(&pb.GridFightGetArchiveCsReq{Type: pb.MLJIILDNDPL_MLJIILDNDPL_FAGECPGMPEH})
if err := typedHandlers[uint16(getArchiveCmdID)](session, rawGetArchive); err != nil {
t.Fatalf("call GridFightGetArchive: %v", err)
entries, err := cwReadArchives(snapshot)
if err != nil || len(entries) == 0 {
t.Fatalf("read archive: %v", err)
}
entry := entries[len(entries)-1]
raw, _ := proto.Marshal(&pb.FavourArchiveCsReq{BAAGDILLLME: entry.BAAGDILLLME, IECKKCHJMLP: true})
if err := typedHandlers[uint16(pb.CmdIDByName["FavourArchiveCsReq"])](session, raw); err != nil {
t.Fatal(err)
}
// A new read/session has no in-memory archive state to rely on.
snapshot, err = cwArchiveSnapshot(c)
if err != nil {
t.Fatal(err)
}
entries, err = cwReadArchives(snapshot)
if err != nil {
t.Fatal(err)
}
if !entries[len(entries)-1].IECKKCHJMLP {
t.Fatal("favourite was not persisted")
}
stale := &Session{currencyWarsRevision: revision}
if err := stale.saveCurrencyWarsTerminal(data, c, record); err == nil {
t.Fatal("stale settlement appended archive")
}
again, err := cwArchiveSnapshot(c)
if err != nil {
t.Fatal(err)
}
if len(again.Archives) != len(snapshot.Archives) {
t.Fatal("failed transaction changed archives")
}
if err := session.saveCurrencyWarsData(data, c); err != nil {
t.Fatal(err)
}
again, err = cwArchiveSnapshot(c)
if err != nil {
t.Fatal(err)
}
if len(again.Archives) != len(snapshot.Archives) {
t.Fatal("ordinary save lost archives")
}
}