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,105 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"longheng.io/server/internal/modules/dnf/dnfenum"
|
||||
)
|
||||
|
||||
const (
|
||||
LegacyChannelHeaderSize = 11
|
||||
DofLoginTokenSize = 32
|
||||
DofLoginPrefaceSize = LegacyChannelHeaderSize + DofLoginTokenSize
|
||||
DofAskChannelSize = 35
|
||||
)
|
||||
|
||||
// IsDofLoginPrefacePrefix 判断连接开头是否为 NoPack/DOF 登录预握手。
|
||||
func IsDofLoginPrefacePrefix(data []byte) bool {
|
||||
return hasLegacyPrefix(data, 0, dnfenum.LegacyMsgDofLoginPreface)
|
||||
}
|
||||
|
||||
// IsDofChannelProbePrefix 判断是否为 NoPack/DOF 预登录中的 0x09 脚本请求。
|
||||
func IsDofChannelProbePrefix(data []byte) bool {
|
||||
return hasLegacyPrefix(data, 0, dnfenum.LegacyMsgDofGetScript)
|
||||
}
|
||||
|
||||
// IsDofAskChannelPrefix 判断是否为 DOF 预登录后的频道目录请求。
|
||||
func IsDofAskChannelPrefix(data []byte) bool {
|
||||
return hasLegacyPrefix(data, 0, dnfenum.LegacyMsgAskChannelInfo)
|
||||
}
|
||||
|
||||
// BuildDofLoginAck 构造 DOF 预登录 ack。
|
||||
//
|
||||
// 真实客户端先只读前 11 字节 ack,后续 4 字节保留位和 32 字节 key
|
||||
// 仍按旧服格式一次写出,避免后续读取阶段缺数据。
|
||||
func BuildDofLoginAck(aesKey string) []byte {
|
||||
body := make([]byte, 36)
|
||||
copy(body[4:], []byte(aesKey))
|
||||
return BuildLegacyChannelPacket(dnfenum.LegacyMsgDofLoginAck, body)
|
||||
}
|
||||
|
||||
// BuildLegacyChannelPacket 构造 DOF 旧式频道包。
|
||||
func BuildLegacyChannelPacket(msg dnfenum.LegacyChannelMsg, body []byte) []byte {
|
||||
return buildLegacyPacket(dnfenum.ChannelPacketClass, msg, body)
|
||||
}
|
||||
|
||||
// BuildLegacyClientPacket 构造测试和兼容入口使用的客户端旧式频道包。
|
||||
func BuildLegacyClientPacket(msg dnfenum.LegacyChannelMsg, body []byte) []byte {
|
||||
total := LegacyChannelHeaderSize + len(body)
|
||||
if fixed := legacyFixedLength(msg); fixed > total {
|
||||
total = fixed
|
||||
}
|
||||
packet := make([]byte, total)
|
||||
writeLegacyHeader(packet[:LegacyChannelHeaderSize], 0, byte(msg), total)
|
||||
copy(packet[LegacyChannelHeaderSize:], body)
|
||||
return packet
|
||||
}
|
||||
|
||||
func buildLegacyPacket(command byte, msg dnfenum.LegacyChannelMsg, body []byte) []byte {
|
||||
packet := make([]byte, LegacyChannelHeaderSize+len(body))
|
||||
writeLegacyHeader(packet[:LegacyChannelHeaderSize], command, byte(msg), len(packet))
|
||||
copy(packet[LegacyChannelHeaderSize:], body)
|
||||
return packet
|
||||
}
|
||||
|
||||
// LegacyPayload 返回旧式频道包的 payload 副本。
|
||||
func LegacyPayload(packet []byte) []byte {
|
||||
if len(packet) <= LegacyChannelHeaderSize {
|
||||
return nil
|
||||
}
|
||||
return cloneBytes(packet[LegacyChannelHeaderSize:])
|
||||
}
|
||||
|
||||
func hasLegacyPrefix(data []byte, command byte, msg dnfenum.LegacyChannelMsg) bool {
|
||||
if len(data) < LegacyChannelHeaderSize {
|
||||
return false
|
||||
}
|
||||
var want [LegacyChannelHeaderSize]byte
|
||||
writeLegacyHeader(want[:], command, byte(msg), legacyFixedLength(msg))
|
||||
return bytes.Equal(data[:LegacyChannelHeaderSize], want[:])
|
||||
}
|
||||
|
||||
func writeLegacyHeader(header []byte, command byte, msgID byte, totalLen int) {
|
||||
header[0] = command
|
||||
header[1] = msgID
|
||||
binary.LittleEndian.PutUint32(header[2:6], uint32(totalLen))
|
||||
header[10] = 1
|
||||
}
|
||||
|
||||
func legacyFixedLength(msg dnfenum.LegacyChannelMsg) int {
|
||||
switch msg {
|
||||
case dnfenum.LegacyMsgDofLoginPreface:
|
||||
return DofLoginPrefaceSize
|
||||
case dnfenum.LegacyMsgDofGetScript:
|
||||
return LegacyChannelHeaderSize
|
||||
case dnfenum.LegacyMsgAskChannelInfo:
|
||||
return DofAskChannelSize
|
||||
default:
|
||||
length := int(uint16(msg) >> 8)
|
||||
if length > 0 {
|
||||
return length
|
||||
}
|
||||
return LegacyChannelHeaderSize
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user