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,331 @@
|
||||
package dnfbridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCurrentPartyUDPRelayDatagramTraceIsBounded(t *testing.T) {
|
||||
for count := uint64(0); count <= 1025; count++ {
|
||||
want := count >= 1 && count <= 8 || count >= 16 && count&(count-1) == 0
|
||||
if got := currentPartyUDPRelayTraceDatagram(count); got != want {
|
||||
t.Fatalf("trace count %d=%t want %t", count, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentPartyUDPRelayForwardsOnlyAuthenticatedDirectedLegs(t *testing.T) {
|
||||
portStart := testCurrentPartyUDPRelayPortStart(t)
|
||||
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("new UDP relay: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := relay.Close(); err != nil {
|
||||
t.Fatalf("close UDP relay: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
bindings := []currentPartyUDPRelayBinding{
|
||||
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}},
|
||||
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}},
|
||||
}
|
||||
if !relay.Sync(77, bindings) {
|
||||
t.Fatal("relay did not create a complete two-member room")
|
||||
}
|
||||
addressAB, portAB, ok := relay.Endpoint(77, 101, 202)
|
||||
if !ok {
|
||||
t.Fatal("missing A-to-B relay endpoint")
|
||||
}
|
||||
addressBA, portBA, ok := relay.Endpoint(77, 202, 101)
|
||||
if !ok || portAB == portBA {
|
||||
t.Fatalf("invalid directed relay endpoints: AB=%d BA=%d ok=%v", portAB, portBA, ok)
|
||||
}
|
||||
|
||||
clientA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientA.Close()
|
||||
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientB.Close()
|
||||
wrongSource := testCurrentPartyUDPClient(t, "127.0.0.2", portStart)
|
||||
defer wrongSource.Close()
|
||||
|
||||
endpointAB := &net.UDPAddr{IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]), Port: int(portAB)}
|
||||
endpointBA := &net.UDPAddr{IP: net.IPv4(addressBA[0], addressBA[1], addressBA[2], addressBA[3]), Port: int(portBA)}
|
||||
if _, err := wrongSource.WriteToUDP([]byte("forged"), endpointAB); err != nil {
|
||||
t.Fatalf("send forged endpoint registration: %v", err)
|
||||
}
|
||||
if _, err := clientB.WriteToUDP([]byte("b-ready"), endpointBA); err != nil {
|
||||
t.Fatalf("send B handshake: %v", err)
|
||||
}
|
||||
if _, err := clientA.WriteToUDP([]byte("A-payload"), endpointAB); err != nil {
|
||||
t.Fatalf("send A payload: %v", err)
|
||||
}
|
||||
|
||||
// B's handshake and A's payload travel on separate sockets, and UDP gives
|
||||
// no cross-socket ordering: on a loaded machine the payload can reach the
|
||||
// relay before the handshake registers B's leg, and the relay rightly
|
||||
// drops it. Resending the payload until it arrives keeps the assertion
|
||||
// about WHAT is forwarded while tolerating WHEN registration wins.
|
||||
buffer := make([]byte, 128)
|
||||
var n int
|
||||
overall := time.Now().Add(5 * time.Second)
|
||||
for {
|
||||
if err := clientB.SetReadDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("set client B deadline: %v", err)
|
||||
}
|
||||
var err error
|
||||
n, _, err = clientB.ReadFromUDP(buffer)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if !errors.Is(err, os.ErrDeadlineExceeded) || time.Now().After(overall) {
|
||||
t.Fatalf("receive relayed payload: %v", err)
|
||||
}
|
||||
if _, err := clientA.WriteToUDP([]byte("A-payload"), endpointAB); err != nil {
|
||||
t.Fatalf("resend A payload: %v", err)
|
||||
}
|
||||
}
|
||||
if !bytes.Equal(buffer[:n], []byte("A-payload")) {
|
||||
t.Fatalf("relayed payload = %q, want A-payload", buffer[:n])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentPartyUDPRelayForwardsFirstHandshakeToRegisteredPeerPort(t *testing.T) {
|
||||
portStart := testCurrentPartyUDPRelayPortStart(t)
|
||||
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("new UDP relay: %v", err)
|
||||
}
|
||||
defer relay.Close()
|
||||
|
||||
clientA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientA.Close()
|
||||
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientB.Close()
|
||||
bindings := []currentPartyUDPRelayBinding{
|
||||
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientA.LocalAddr().(*net.UDPAddr).Port)},
|
||||
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientB.LocalAddr().(*net.UDPAddr).Port)},
|
||||
}
|
||||
if !relay.Sync(78, bindings) {
|
||||
t.Fatal("relay did not create registered two-member room")
|
||||
}
|
||||
addressAB, portAB, ok := relay.Endpoint(78, 101, 202)
|
||||
if !ok {
|
||||
t.Fatal("missing A-to-B relay endpoint")
|
||||
}
|
||||
endpointAB := &net.UDPAddr{IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]), Port: int(portAB)}
|
||||
if _, err := clientA.WriteToUDP([]byte("first-handshake"), endpointAB); err != nil {
|
||||
t.Fatalf("send first handshake: %v", err)
|
||||
}
|
||||
|
||||
buffer := make([]byte, 128)
|
||||
if err := clientB.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
||||
t.Fatalf("set client B deadline: %v", err)
|
||||
}
|
||||
n, _, err := clientB.ReadFromUDP(buffer)
|
||||
if err != nil {
|
||||
t.Fatalf("receive first relayed handshake: %v", err)
|
||||
}
|
||||
if !bytes.Equal(buffer[:n], []byte("first-handshake")) {
|
||||
t.Fatalf("first relayed handshake = %q", buffer[:n])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentPartyUDPRelayLearnsActivePartySocketAfterSeededProbePort(t *testing.T) {
|
||||
portStart := testCurrentPartyUDPRelayPortStart(t)
|
||||
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("new UDP relay: %v", err)
|
||||
}
|
||||
defer relay.Close()
|
||||
|
||||
probeA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer probeA.Close()
|
||||
partyA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer partyA.Close()
|
||||
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientB.Close()
|
||||
bindings := []currentPartyUDPRelayBinding{
|
||||
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(probeA.LocalAddr().(*net.UDPAddr).Port)},
|
||||
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientB.LocalAddr().(*net.UDPAddr).Port)},
|
||||
}
|
||||
if !relay.Sync(79, bindings) {
|
||||
t.Fatal("relay did not create seeded two-member room")
|
||||
}
|
||||
addressAB, portAB, ok := relay.Endpoint(79, 101, 202)
|
||||
if !ok {
|
||||
t.Fatal("missing A-to-B relay endpoint")
|
||||
}
|
||||
addressBA, portBA, ok := relay.Endpoint(79, 202, 101)
|
||||
if !ok {
|
||||
t.Fatal("missing B-to-A relay endpoint")
|
||||
}
|
||||
endpointAB := &net.UDPAddr{IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]), Port: int(portAB)}
|
||||
endpointBA := &net.UDPAddr{IP: net.IPv4(addressBA[0], addressBA[1], addressBA[2], addressBA[3]), Port: int(portBA)}
|
||||
if _, err := partyA.WriteToUDP([]byte("A-live-source"), endpointAB); err != nil {
|
||||
t.Fatalf("send A live-source handshake: %v", err)
|
||||
}
|
||||
buffer := make([]byte, 128)
|
||||
if err := clientB.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
||||
t.Fatalf("set B read deadline: %v", err)
|
||||
}
|
||||
if _, _, err := clientB.ReadFromUDP(buffer); err != nil {
|
||||
t.Fatalf("receive A handshake at seeded B endpoint: %v", err)
|
||||
}
|
||||
if _, err := clientB.WriteToUDP([]byte("B-reply"), endpointBA); err != nil {
|
||||
t.Fatalf("send B reply: %v", err)
|
||||
}
|
||||
if err := partyA.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
||||
t.Fatalf("set A live socket deadline: %v", err)
|
||||
}
|
||||
n, _, err := partyA.ReadFromUDP(buffer)
|
||||
if err != nil {
|
||||
t.Fatalf("receive B reply at learned A party socket: %v", err)
|
||||
}
|
||||
if !bytes.Equal(buffer[:n], []byte("B-reply")) {
|
||||
t.Fatalf("learned A party socket payload=%q", buffer[:n])
|
||||
}
|
||||
if err := probeA.SetReadDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("set A probe deadline: %v", err)
|
||||
}
|
||||
if _, _, err := probeA.ReadFromUDP(buffer); err == nil {
|
||||
t.Fatal("B reply was still delivered to the inactive seeded probe socket")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentPartyUDPRelayPreservesLargeRealtimeActorDatagram(t *testing.T) {
|
||||
portStart := testCurrentPartyUDPRelayPortStart(t)
|
||||
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("new UDP relay: %v", err)
|
||||
}
|
||||
defer relay.Close()
|
||||
|
||||
clientA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientA.Close()
|
||||
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
|
||||
defer clientB.Close()
|
||||
bindings := []currentPartyUDPRelayBinding{
|
||||
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientA.LocalAddr().(*net.UDPAddr).Port)},
|
||||
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientB.LocalAddr().(*net.UDPAddr).Port)},
|
||||
}
|
||||
if !relay.Sync(80, bindings) {
|
||||
t.Fatal("relay did not create large-datagram test room")
|
||||
}
|
||||
addressAB, portAB, ok := relay.Endpoint(80, 101, 202)
|
||||
if !ok {
|
||||
t.Fatal("missing A-to-B relay endpoint")
|
||||
}
|
||||
|
||||
// Exceeds the former 2 KiB buffer and models one complete reliable actor
|
||||
// snapshot containing riding/transform plus combat state.
|
||||
payload := make([]byte, 32*1024)
|
||||
for index := range payload {
|
||||
payload[index] = byte(index*31 + 7)
|
||||
}
|
||||
endpointAB := &net.UDPAddr{
|
||||
IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]),
|
||||
Port: int(portAB),
|
||||
}
|
||||
if _, err := clientA.WriteToUDP(payload, endpointAB); err != nil {
|
||||
t.Fatalf("send large actor datagram: %v", err)
|
||||
}
|
||||
|
||||
buffer := make([]byte, len(payload)+1)
|
||||
if err := clientB.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
||||
t.Fatalf("set client B deadline: %v", err)
|
||||
}
|
||||
n, _, err := clientB.ReadFromUDP(buffer)
|
||||
if err != nil {
|
||||
t.Fatalf("receive large actor datagram: %v", err)
|
||||
}
|
||||
if n != len(payload) || !bytes.Equal(buffer[:n], payload) {
|
||||
t.Fatalf("large actor datagram bytes=%d want=%d equal=%t", n, len(payload), bytes.Equal(buffer[:n], payload))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrentPartyUDPRelaySyncRemovesFormerMemberLegs(t *testing.T) {
|
||||
portStart := testCurrentPartyUDPRelayPortStart(t)
|
||||
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("new UDP relay: %v", err)
|
||||
}
|
||||
defer relay.Close()
|
||||
|
||||
first := []currentPartyUDPRelayBinding{
|
||||
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}},
|
||||
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}},
|
||||
{characterID: 303, generation: 1, address: [4]byte{127, 0, 0, 1}},
|
||||
}
|
||||
if !relay.Sync(77, first) {
|
||||
t.Fatal("initial relay sync failed")
|
||||
}
|
||||
if _, _, ok := relay.Endpoint(77, 101, 303); !ok {
|
||||
t.Fatal("initial member endpoint missing")
|
||||
}
|
||||
if !relay.Sync(77, first[:2]) {
|
||||
t.Fatal("member removal relay sync failed")
|
||||
}
|
||||
if _, _, ok := relay.Endpoint(77, 101, 303); ok {
|
||||
t.Fatal("former member endpoint remained routable")
|
||||
}
|
||||
if _, _, ok := relay.Endpoint(77, 101, 202); !ok {
|
||||
t.Fatal("remaining pair endpoint was removed")
|
||||
}
|
||||
}
|
||||
|
||||
// testCurrentPartyUDPRelayPortSpan is how many ports the relay may bind its legs
|
||||
// from in these tests. It is shared with testCurrentPartyUDPClient so that a test
|
||||
// client socket can never land on one of the legs' port numbers.
|
||||
const testCurrentPartyUDPRelayPortSpan = 12
|
||||
|
||||
func testCurrentPartyUDPRelayPortStart(t *testing.T) int {
|
||||
t.Helper()
|
||||
for attempt := 0; attempt < 20; attempt++ {
|
||||
listener, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
|
||||
if err != nil {
|
||||
t.Fatalf("allocate test UDP port: %v", err)
|
||||
}
|
||||
port := listener.LocalAddr().(*net.UDPAddr).Port
|
||||
_ = listener.Close()
|
||||
if port <= 65523 {
|
||||
return port
|
||||
}
|
||||
}
|
||||
t.Fatal("could not allocate a usable twelve-port UDP test range")
|
||||
return 0
|
||||
}
|
||||
|
||||
// testCurrentPartyUDPClient listens on an ephemeral loopback port that is kept
|
||||
// outside the relay's own port window.
|
||||
//
|
||||
// The relay binds its legs on the wildcard address (0.0.0.0:port, deliberately:
|
||||
// see newCurrentPartyUDPRelay) while this helper binds a specific address
|
||||
// (127.0.0.1:port). Windows lets both exist, and the specific bind wins delivery,
|
||||
// so a client socket that happened to land on a leg's port number silently
|
||||
// swallowed every datagram addressed to that leg -- the relay then looked like it
|
||||
// had failed to forward when in fact nothing ever reached it. The window start is
|
||||
// handed in by the caller so the two allocations can never overlap.
|
||||
func testCurrentPartyUDPClient(t *testing.T, ip string, windowStart int) *net.UDPConn {
|
||||
t.Helper()
|
||||
for attempt := 0; attempt < 64; attempt++ {
|
||||
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.ParseIP(ip), Port: 0})
|
||||
if err != nil {
|
||||
t.Fatalf("listen UDP client %s: %v", ip, err)
|
||||
}
|
||||
port := conn.LocalAddr().(*net.UDPAddr).Port
|
||||
if port < windowStart || port >= windowStart+testCurrentPartyUDPRelayPortSpan {
|
||||
return conn
|
||||
}
|
||||
// Give the port back: the relay is about to bind this same number on the
|
||||
// wildcard address, and holding it here would shadow that leg.
|
||||
_ = conn.Close()
|
||||
}
|
||||
t.Fatalf("could not place UDP client %s outside relay window %d..%d",
|
||||
ip, windowStart, windowStart+testCurrentPartyUDPRelayPortSpan-1)
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user