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,370 @@
|
||||
package dnfbridge
|
||||
|
||||
import (
|
||||
"context"
|
||||
dnfcharstat "longheng.io/server/internal/modules/dnf/charstat"
|
||||
dnfrepo "longheng.io/server/internal/modules/dnf/repository"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const csharpLegacyUserInfoKind = "legacy_userinfo"
|
||||
|
||||
func csharpLegacyUserInfoInitPackets() []csharpSelectInitPacket {
|
||||
// 0x015d 是角色栏解锁相关通知,不能放进选择角色主动初始化;基础 8 栏由 roster 字段默认开放。
|
||||
// C# registry 中部分上下文刷新包仅保留 builder,不放入 active init,避免进入角色后重复推栏位/上下文状态。
|
||||
ids := []uint16{
|
||||
0x0023, 0x0047,
|
||||
0x0057, 0x0058, 0x0059, 0x005b, 0x005c, 0x005f, 0x005a,
|
||||
0x0060, 0x0064, 0x0067, 0x006a, 0x006b, 0x0073, 0x007a,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008f, 0x0090, 0x0091, 0x0092, 0x0098,
|
||||
0x009b, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00aa, 0x00b0,
|
||||
0x00b6, 0x00bc, 0x00c8, 0x00c9, 0x00cf, 0x00d0, 0x00d1,
|
||||
0x00d2, 0x00d3, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00dc,
|
||||
0x00dd, 0x00df, 0x00e0, 0x00e3, 0x00e6, 0x00eb, 0x00fe,
|
||||
0x00ff, 0x0103, 0x0109, 0x010c, 0x0114, 0x0115, 0x0117,
|
||||
0x0118, 0x011d, 0x0126, 0x012a, 0x012d, 0x0154, 0x0159,
|
||||
0x017c, 0x0182, 0x0183, 0x0184, 0x0186, 0x0192,
|
||||
0x022d, 0x022e, 0x0237, 0x0238, 0x0253, 0x0254, 0x0255,
|
||||
0x025b, 0x026e, 0x0274, 0x0275, 0x0276, 0x0287, 0x028a,
|
||||
0x028b, 0x029f, 0x02a9, 0x02aa, 0x02b0, 0x02bc, 0x02c1,
|
||||
0x02d2, 0x02d3, 0x02d8, 0x02ef, 0x0311, 0x0312, 0x031d,
|
||||
0x0324, 0x0336, 0x034b,
|
||||
0x034c, 0x034d, 0x034e, 0x0352, 0x0354, 0x0355, 0x0359,
|
||||
0x036b, 0x037b, 0x0393, 0x03c7, 0x03cd, 0x03d0,
|
||||
0x03e6, 0x03e7, 0x03e8, 0x03f3, 0x03fd, 0x0400, 0x0406,
|
||||
0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040d,
|
||||
0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0415,
|
||||
0x0416, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
|
||||
0x041e, 0x0424, 0x0425, 0x0428, 0x0429, 0x042a, 0x042c,
|
||||
0x042d, 0x042e, 0x0430, 0x0435, 0x043e, 0x043f, 0x0440,
|
||||
0x044e, 0x044f, 0x0457, 0x0458, 0x0459, 0x045a, 0x045f,
|
||||
0x0462, 0x0469, 0x046b, 0x046c, 0x046e, 0x046f, 0x0470,
|
||||
0x048c, 0x048e, 0x048f, 0x04a6, 0x04a7, 0x04a9, 0x04aa,
|
||||
0x04b0, 0x04b1, 0x04b2, 0x04c6, 0x04c7, 0x04c8, 0x04ca,
|
||||
0x04d4, 0x04d5, 0x04da, 0x04db, 0x04df, 0x04e2, 0x04ec,
|
||||
0x04f0, 0x04f1, 0x04f8, 0x04fe, 0x04ff, 0x0508, 0x050a,
|
||||
0x050b, 0x050c, 0x050d, 0x0514, 0x0515, 0x0516, 0x0517,
|
||||
0x0518, 0x052b, 0x052c, 0x052f, 0x0532, 0x0533, 0x0534,
|
||||
0x0547, 0x0549,
|
||||
}
|
||||
packets := make([]csharpSelectInitPacket, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
packets = append(packets, csharpSelectInitPacket{class: 0, msgID: id, kind: csharpLegacyUserInfoKind})
|
||||
}
|
||||
return packets
|
||||
}
|
||||
|
||||
type csharpLegacyUserInfoReader struct {
|
||||
ctx context.Context
|
||||
repo dnfrepo.LegacyUserInfoRepository
|
||||
characterID string
|
||||
service *Service
|
||||
session *gameSession
|
||||
pvfStats dnfcharstat.Vector
|
||||
hasPVFStats bool
|
||||
// suppressActorSkillResources 用于「为已存在的 actor 重新绑定上下文」的场景:
|
||||
// 这种重绑不能重播已学技能资源,否则客户端会看到技能页被再次点亮。
|
||||
// (支援兵的 mode1 就是这种场景,见 dungeon_companion_balance.go。)
|
||||
suppressActorSkillResources bool
|
||||
// equipmentSnapshot 非空时用这份冻结的装备记录替代仓储读取 —— 支援兵的
|
||||
// 临时平衡装备只存在于运行态,没有落库。
|
||||
equipmentSnapshot *dnfrepo.EquipmentRecord
|
||||
// peerSkills 是决斗场房间演员专用的技能页投影(见 pvp_skills.go)。
|
||||
// 非空时覆盖常规技能页;为空时沿用本树原有的 currentUserInfoSkillPages。
|
||||
peerSkills []byte
|
||||
loaded bool
|
||||
}
|
||||
|
||||
func (s *Service) buildCSharpLegacyUserInfoBody(ctx context.Context, session *gameSession, repo dnfrepo.LegacyUserInfoRepository, charID uint16, msgID uint16) ([]byte, bool) {
|
||||
if repo == nil {
|
||||
return nil, false
|
||||
}
|
||||
reader := csharpLegacyUserInfoReader{
|
||||
ctx: ctx,
|
||||
repo: repo,
|
||||
characterID: strconv.Itoa(int(charID)),
|
||||
service: s,
|
||||
session: session,
|
||||
}
|
||||
var body []byte
|
||||
switch msgID {
|
||||
case 0x0023:
|
||||
body = reader.build23()
|
||||
case 0x0047:
|
||||
body = reader.build47()
|
||||
case 0x0057:
|
||||
body = reader.build57()
|
||||
case 0x0058:
|
||||
body = reader.build58()
|
||||
case 0x0059:
|
||||
body = reader.build59()
|
||||
case 0x005b:
|
||||
body = reader.build5B()
|
||||
case 0x005c:
|
||||
body = reader.build5C()
|
||||
case 0x005f:
|
||||
body = reader.build5F()
|
||||
case 0x005a, 0x0082, 0x00e3, 0x0103, 0x0114, 0x0115, 0x012d, 0x0186, 0x0192, 0x01d5, 0x01d6, 0x0376:
|
||||
return nil, true
|
||||
case 0x0060:
|
||||
body = reader.build60()
|
||||
case 0x0064:
|
||||
body = reader.buildOneU16("legacy_character_userinfo64_state", "object_key")
|
||||
case 0x0067:
|
||||
body = reader.buildTwoU32("legacy_character_userinfo67_state", "value_a", "value_b")
|
||||
case 0x006a:
|
||||
body = reader.build6A()
|
||||
case 0x006b:
|
||||
body = reader.buildOneU16("legacy_character_userinfo6b_state", "object_key")
|
||||
case 0x0073:
|
||||
body = reader.build73()
|
||||
case 0x007a:
|
||||
body = reader.build7A()
|
||||
case 0x0080:
|
||||
body = reader.build80()
|
||||
case 0x0081:
|
||||
body = reader.buildOneU16("legacy_character_userinfo81_state", "value")
|
||||
case 0x0083:
|
||||
body = reader.buildOneU16("legacy_character_userinfo83_state", "value")
|
||||
case 0x0085:
|
||||
body = reader.buildOneU16("legacy_character_userinfo85_state", "object_key")
|
||||
case 0x0086:
|
||||
body = reader.build86()
|
||||
case 0x0087:
|
||||
body = reader.buildOneU16("legacy_character_userinfo87_state", "value")
|
||||
case 0x0088:
|
||||
body = reader.build88()
|
||||
case 0x0089:
|
||||
body = reader.buildOneU8("legacy_character_userinfo89_state", "state")
|
||||
case 0x008f:
|
||||
body = reader.build8F()
|
||||
case 0x0090:
|
||||
body = reader.build90()
|
||||
case 0x0091:
|
||||
body = reader.build91()
|
||||
case 0x0092:
|
||||
body = reader.buildOneU8("legacy_character_userinfo92_state", "mode_flag")
|
||||
case 0x0098:
|
||||
body = reader.build98()
|
||||
case 0x009b:
|
||||
body = reader.buildTwoU32("legacy_character_userinfo9b_state", "value_a", "value_b")
|
||||
case 0x00a0:
|
||||
body = reader.buildA0()
|
||||
case 0x00a1:
|
||||
body = reader.buildA1()
|
||||
case 0x00a2:
|
||||
body = reader.buildA2()
|
||||
case 0x00a3:
|
||||
body = reader.buildOneU32("legacy_character_userinfoa3_state", "value")
|
||||
case 0x00aa:
|
||||
body = reader.buildAA()
|
||||
case 0x00b0:
|
||||
body = reader.buildOneU8("legacy_character_userinfob0_state", "enabled")
|
||||
case 0x00b6:
|
||||
body = reader.buildB6()
|
||||
case 0x00bc:
|
||||
body = reader.buildOneU8("legacy_character_userinfobc_state", "state")
|
||||
case 0x00c8:
|
||||
body = reader.buildOneU8("legacy_character_userinfoc8_state", "delta")
|
||||
case 0x00c9:
|
||||
body = reader.buildC9()
|
||||
case 0x00cf:
|
||||
body = reader.buildOneU32("legacy_character_userinfocf_state", "value")
|
||||
case 0x00d0:
|
||||
body = reader.buildD0()
|
||||
case 0x00d1:
|
||||
body = reader.buildD1()
|
||||
case 0x00d2:
|
||||
body = reader.buildD2()
|
||||
case 0x00d3:
|
||||
body = reader.buildD3()
|
||||
case 0x00d5:
|
||||
body = reader.buildD5Like("legacy_character_userinfod5_state")
|
||||
case 0x00d6:
|
||||
body = reader.buildD6()
|
||||
case 0x00d7:
|
||||
body = reader.buildD7()
|
||||
case 0x00d8:
|
||||
body = reader.buildD8()
|
||||
case 0x00dc:
|
||||
body = reader.buildOneU32("legacy_character_userinfodc_state", "value")
|
||||
case 0x00dd:
|
||||
body = reader.buildTwoU32("legacy_character_userinfodd_state", "value_a", "value_b")
|
||||
case 0x00df:
|
||||
body = reader.buildDF()
|
||||
case 0x00e0:
|
||||
body = reader.buildE0()
|
||||
case 0x00e6:
|
||||
body = reader.buildOneU8("legacy_character_userinfoe6_state", "value")
|
||||
case 0x00eb:
|
||||
body = reader.buildOneU16("legacy_character_userinfoeb_state", "value")
|
||||
case 0x00fe:
|
||||
body = reader.buildFE()
|
||||
case 0x00ff:
|
||||
body = reader.buildD5Like("legacy_character_userinfoff_state")
|
||||
case 0x0109:
|
||||
body = reader.build109()
|
||||
case 0x010c:
|
||||
body = reader.buildOneU16("legacy_character_userinfo10c_state", "value")
|
||||
case 0x0117:
|
||||
body = reader.buildOneU32("legacy_character_userinfo117_state", "value")
|
||||
case 0x0118:
|
||||
body = reader.build118()
|
||||
case 0x011d:
|
||||
body = reader.build11D()
|
||||
case 0x0126:
|
||||
body = reader.build126()
|
||||
case 0x012a:
|
||||
body = reader.buildD5Like("legacy_character_userinfo12a_state")
|
||||
case 0x0154:
|
||||
body = reader.build154()
|
||||
case 0x0159:
|
||||
body = reader.build159()
|
||||
case 0x017c:
|
||||
body = reader.build17C()
|
||||
case 0x0182:
|
||||
body = reader.build182()
|
||||
case 0x0183:
|
||||
body = reader.build183()
|
||||
case 0x0184:
|
||||
body = reader.build184()
|
||||
case 0x01bf:
|
||||
body = reader.build1BF()
|
||||
case 0x022d:
|
||||
body = reader.build22D()
|
||||
case 0x022e:
|
||||
body = reader.build22E()
|
||||
case 0x0237:
|
||||
body = reader.buildConditionalOneU32("legacy_character_userinfo237_state", "value")
|
||||
case 0x0238:
|
||||
body = reader.buildConditionalOneU32("legacy_character_userinfo238_state", "value")
|
||||
case 0x0253:
|
||||
body = reader.build253()
|
||||
case 0x0254:
|
||||
body = reader.build254()
|
||||
case 0x0255:
|
||||
body = reader.buildConditionalOneU16("legacy_character_userinfo255_state", "value")
|
||||
case 0x025b:
|
||||
body = reader.build25B()
|
||||
case 0x026e:
|
||||
body = reader.build26E()
|
||||
case 0x0274:
|
||||
body = reader.buildConditionalOneU32("legacy_character_userinfo274_state", "value")
|
||||
case 0x0275:
|
||||
body = reader.build275()
|
||||
case 0x0276:
|
||||
body = reader.build276()
|
||||
case 0x0287:
|
||||
body = reader.build287()
|
||||
case 0x028a:
|
||||
body = reader.build28A()
|
||||
case 0x028b:
|
||||
body = reader.build28B()
|
||||
case 0x029f:
|
||||
body = reader.build29F()
|
||||
case 0x02a9:
|
||||
body = reader.build2A9()
|
||||
case 0x02aa:
|
||||
body = reader.build2AA()
|
||||
case 0x02b0:
|
||||
body = reader.build2B0()
|
||||
case 0x02bc:
|
||||
body = reader.build2BC()
|
||||
case 0x02c1:
|
||||
body = reader.build2C1()
|
||||
case 0x02d2:
|
||||
body = reader.build2D2()
|
||||
case 0x02d3:
|
||||
body = reader.buildOneU32IfPresent("legacy_character_userinfo2d3_state", "value")
|
||||
case 0x02d8:
|
||||
body = reader.buildOneU32IfPresent("legacy_character_userinfo2d8_state", "value")
|
||||
case 0x02ef:
|
||||
body = reader.buildOneU32IfPresent("legacy_character_userinfo2ef_state", "value")
|
||||
case 0x031d:
|
||||
body = reader.buildOneU8IfPresent("legacy_character_userinfo31d_state", "value")
|
||||
case 0x0324:
|
||||
body = reader.build324()
|
||||
case 0x0327:
|
||||
body = reader.build327()
|
||||
case 0x0329:
|
||||
body = reader.build329()
|
||||
case 0x0336:
|
||||
body = reader.build336()
|
||||
case 0x034b:
|
||||
body = reader.build34B()
|
||||
case 0x034c:
|
||||
body = reader.build34CText()
|
||||
case 0x034d:
|
||||
body = reader.build34DValue()
|
||||
case 0x034e:
|
||||
body = reader.build34EByte()
|
||||
case 0x0352:
|
||||
body = reader.build352()
|
||||
case 0x0354:
|
||||
body = reader.build354()
|
||||
case 0x0355:
|
||||
body = reader.buildOneU32IfPresent("legacy_character_userinfo355_state", "value")
|
||||
case 0x0359:
|
||||
body = reader.build359()
|
||||
case 0x036b:
|
||||
body = reader.build36B()
|
||||
case 0x0161:
|
||||
body = reader.buildRawFixed(0x0161, 1)
|
||||
case 0x01d4:
|
||||
body = reader.buildRawByteCountList(0x01d4, 8)
|
||||
case 0x01d7:
|
||||
body = reader.buildRawByteCountList(0x01d7, 7)
|
||||
case 0x01d8:
|
||||
body = reader.buildRawByteCountList(0x01d8, 7)
|
||||
case 0x01d9:
|
||||
body = reader.buildRawFixed(0x01d9, 1)
|
||||
case 0x0343:
|
||||
body = reader.buildRawFixed(0x0343, 1)
|
||||
case 0x0344:
|
||||
body = reader.buildRawFixed(0x0344, 24)
|
||||
case 0x0373:
|
||||
body = reader.buildRawFixed(0x0373, 8)
|
||||
case 0x0374:
|
||||
body = reader.build374()
|
||||
case 0x0375:
|
||||
body = reader.buildRawFixed(0x0375, 38)
|
||||
case 0x0377:
|
||||
body = reader.buildRawFixed(0x0377, 8)
|
||||
case 0x0378:
|
||||
body = reader.buildRawFixed(0x0378, 5)
|
||||
case 0x0379:
|
||||
body = reader.build379()
|
||||
case 0x037a:
|
||||
body = reader.build37A()
|
||||
case 0x037b:
|
||||
body = reader.build37B()
|
||||
case 0x0393:
|
||||
body = reader.build393()
|
||||
case 0x03cd:
|
||||
body = reader.build3CD()
|
||||
case 0x03e6:
|
||||
body = reader.buildOneU8IfPresent("legacy_character_userinfo3e6_state", "value")
|
||||
case currentRaidDailyAvailabilityMsgID:
|
||||
// Fixture/template path: the live send in sendCurrentRaidDailyAvailability
|
||||
// reads the account's real counters, this one only needs the fixed shape.
|
||||
structured, err := buildCurrentRaidDailyAvailabilityBody(defaultCurrentRaidDailyAvailabilityRows())
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
body = structured
|
||||
reader.loaded = true
|
||||
default:
|
||||
if expectedLength, ok := csharpRawFixedUserInfoLength(msgID); ok {
|
||||
body = reader.buildRawFixed(msgID, expectedLength)
|
||||
} else if csharpRawUserInfoBody(msgID) {
|
||||
body = reader.buildRawBody(msgID)
|
||||
} else {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
if !reader.loaded {
|
||||
return nil, false
|
||||
}
|
||||
return body, true
|
||||
}
|
||||
Reference in new issue
Block a user