DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go): - GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面 - GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新 - 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新) - 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍 - 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0) - 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算 启动器(Python/JS): - 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭 - GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐) - 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
This commit is contained in:
commit
645b64fe21
4388 files changed
+1405457
No files matched your search
@@ -0,0 +1,114 @@
|
||||
package companion
|
||||
|
||||
import "testing"
|
||||
|
||||
func retirementInstance(t *testing.T, withActor bool) (*Instance, RunKey) {
|
||||
t.Helper()
|
||||
key := runKey()
|
||||
i, err := NewInstance(key, prepared(t), 1, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := i.Apply(Event{Run: key, Sequence: 1, Kind: "room_ready", RoomGeneration: 1}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if withActor {
|
||||
for n, kind := range []string{"native_created", "owner_bound", "activate"} {
|
||||
if err := i.Apply(Event{Run: key, Sequence: uint64(n + 2), Kind: kind, RoomGeneration: 1, ObjectKey: 24, ObjectGeneration: 7}, map[uint16]bool{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
seq := i.Status().LastSequence + 1
|
||||
if err := i.Apply(Event{Run: key, Sequence: seq, Kind: "retire", RoomGeneration: 1}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return i, key
|
||||
}
|
||||
|
||||
func TestCompanionDisposedRequiresExactActorAndRoom(t *testing.T) {
|
||||
i, key := retirementInstance(t, true)
|
||||
before := i.Status()
|
||||
valid := Event{Run: key, Sequence: before.LastSequence + 1, Kind: "disposed", RoomGeneration: 1, ObjectKey: 24, ObjectGeneration: 7}
|
||||
for _, field := range []string{"key", "generation", "room", "empty"} {
|
||||
e := valid
|
||||
switch field {
|
||||
case "key":
|
||||
e.ObjectKey++
|
||||
case "generation":
|
||||
e.ObjectGeneration++
|
||||
case "room":
|
||||
e.RoomGeneration++
|
||||
case "empty":
|
||||
e.ObjectKey = 0
|
||||
e.ObjectGeneration = 0
|
||||
}
|
||||
if err := i.Apply(e, nil); err == nil {
|
||||
t.Fatalf("accepted mismatched %s disposal", field)
|
||||
}
|
||||
if i.Status() != before || !i.Owns(key, 24, 7) {
|
||||
t.Fatalf("invalid disposal revoked owner: %s", field)
|
||||
}
|
||||
}
|
||||
if err := i.Apply(valid, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i.Owns(key, 24, 7) || i.Status().Phase != Disposed {
|
||||
t.Fatal("valid disposal did not close")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompanionLateCreationTracksCleanupWithoutAuthorization(t *testing.T) {
|
||||
i, key := retirementInstance(t, false)
|
||||
e := Event{Run: key, Sequence: 3, Kind: "native_created", RoomGeneration: 1, ObjectKey: 24, ObjectGeneration: 7}
|
||||
if err := i.Apply(e, map[uint16]bool{}); err != nil {
|
||||
t.Fatal("late creation lost:", err)
|
||||
}
|
||||
if i.Status().Phase != Retiring || i.Owns(key, 24, 7) {
|
||||
t.Fatal("late creation resurrected cancelled run")
|
||||
}
|
||||
if err := i.Apply(e, map[uint16]bool{}); err != nil {
|
||||
t.Fatal("exact duplicate should be idempotent", err)
|
||||
}
|
||||
if err := i.Apply(Event{Run: key, Sequence: 4, Kind: "owner_bound", RoomGeneration: 1, ObjectKey: 24, ObjectGeneration: 7}, nil); err == nil {
|
||||
t.Fatal("late actor authorized")
|
||||
}
|
||||
if err := i.Apply(Event{Run: key, Sequence: 4, Kind: "disposed", RoomGeneration: 1, ObjectKey: 24, ObjectGeneration: 7}, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i.Status().Phase != Disposed {
|
||||
t.Fatal(i.Status())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompanionLateCreationCannotReplaceExistingActor(t *testing.T) {
|
||||
i, key := retirementInstance(t, true)
|
||||
before := i.Status()
|
||||
e := Event{Run: key, Sequence: before.LastSequence + 1, Kind: "native_created", RoomGeneration: 1, ObjectKey: 25, ObjectGeneration: 8}
|
||||
if err := i.Apply(e, map[uint16]bool{}); err == nil {
|
||||
t.Fatal("replaced retiring actor")
|
||||
}
|
||||
if i.Status() != before {
|
||||
t.Fatal("rejected late creation changed state")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompanionCancellationWithoutActorRequiresEmptyDisposal(t *testing.T) {
|
||||
i, key := retirementInstance(t, false)
|
||||
before := i.Status()
|
||||
e := Event{Run: key, Sequence: 3, Kind: "disposed", RoomGeneration: 1, ObjectKey: 24, ObjectGeneration: 7}
|
||||
if err := i.Apply(e, nil); err == nil {
|
||||
t.Fatal("undisclosed actor disposal accepted")
|
||||
}
|
||||
if i.Status() != before {
|
||||
t.Fatal("bad disposal changed state")
|
||||
}
|
||||
e.ObjectKey = 0
|
||||
e.ObjectGeneration = 0
|
||||
if err := i.Apply(e, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i.Status().Phase != Disposed {
|
||||
t.Fatal(i.Status())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user