fix(scene): unlock all teleports across maps, merge resource configs, fix scenary not load error, and add quick farm battle handlers
This commit is contained in:
1 parent
9aab62414f
commit
163d4433e6
47 files changed
+2025067
-6082
No files matched your search
@@ -1,6 +1,11 @@
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"gac-hkrpg-go/internal/common"
|
||||
goproto "gac-hkrpg-go/protocol/proto"
|
||||
)
|
||||
|
||||
@@ -57,6 +62,7 @@ func init() {
|
||||
simpleReply([]uint16{2966}, 2955, []byte{0x30, 0x00}) // tag 6 retcode 0
|
||||
simpleReply([]uint16{2916}, 2906, []byte{0x18, 0x00}) // tag 3 retcode 0
|
||||
simpleReply([]uint16{2919}, 2928, []byte{0x48, 0x00}) // tag 9 retcode 0
|
||||
simpleReply([]uint16{2974}, 2919, []byte{0x18, 0x00}) // GetFriendListInfo tag 3 retcode 0
|
||||
simpleReply([]uint16{740}, 733, []byte{0x58, 0x00}) // tag 11 retcode 0
|
||||
simpleReply([]uint16{1748}, 1745, []byte{0x08, 0x00}) // tag 1 retcode 0
|
||||
simpleReply([]uint16{1765}, 1730, []byte{0x08, 0x00}) // tag 1 retcode 0
|
||||
@@ -64,7 +70,7 @@ func init() {
|
||||
simpleReply([]uint16{1738}, 1748, nil) // empty body
|
||||
simpleReply([]uint16{188}, 181, []byte{0x50, 0x00}) // tag 10 retcode 0
|
||||
simpleReply([]uint16{4130}, 4124, []byte{0x70, 0x00}) // tag 14 retcode 0
|
||||
simpleReply([]uint16{8110, 8115}, 8104, []byte{0x18, 0x00}) // GetSwitchHandData tag 3 retcode 0
|
||||
simpleReply([]uint16{8110, 8115}, 8108, []byte{0x18, 0x00}) // GetSwitchHandData tag 3 retcode 0 (4.6.51 CmdID: 8108)
|
||||
simpleReply([]uint16{8993, 8991}, 8981, []byte{0x70, 0x00}) // 4.6.51: tag 14 retcode 0
|
||||
simpleReply([]uint16{8987}, 8986, []byte{0x38, 0x00}) // ConfirmChallengeTierceStageSettle tag 7 retcode 0
|
||||
|
||||
@@ -81,21 +87,24 @@ func init() {
|
||||
rawHandlers[1731] = handleStartChallenge
|
||||
rawHandlers[1793] = handleStartChallenge
|
||||
rawHandlers[8986] = handleStartChallengeTierce
|
||||
rawHandlers[8983] = handleStartChallengeTierce
|
||||
rawHandlers[8988] = handleStartChallengeTierce
|
||||
rawHandlers[8978] = handleSetChallengeTierceLineup
|
||||
rawHandlers[9000] = handleSetChallengeTierceLineup
|
||||
rawHandlers[1705] = handleLeaveChallenge
|
||||
rawHandlers[1760] = handleLeaveChallenge
|
||||
rawHandlers[1788] = handleLeaveChallenge
|
||||
rawHandlers[8989] = handleLeaveChallengeTierce
|
||||
rawHandlers[8998] = handleLeaveChallengeTierce
|
||||
rawHandlers[1739] = handleTakeChallengeReward
|
||||
|
||||
// ---- 400 -> Ex-Rank / Affinitive Eidolon Unlock ----
|
||||
rawHandlers[400] = handleExRankUnlock
|
||||
}
|
||||
|
||||
// challengeGroupStatsReply ports the 1775/1711 arm: pull group_id (field 12
|
||||
// varint) from the request and answer cmd 1708 with per-mode statistics.
|
||||
func challengeGroupStatsReply(s *Session, payload []byte) error {
|
||||
groupID := uint32(100)
|
||||
// handleExRankUnlock handles CmdID 400 (Affinitive Eidolon / Ex-Rank unlock request from client).
|
||||
func handleExRankUnlock(s *Session, payload []byte) error {
|
||||
Log(fmt.Sprintf("[EX-RANK] Received cmd 400 (len: %d) payload: %x", len(payload), payload))
|
||||
|
||||
var parsedVal uint32
|
||||
buf := payload
|
||||
for len(buf) > 0 {
|
||||
tag, n := readUvarint(buf)
|
||||
@@ -103,91 +112,131 @@ func challengeGroupStatsReply(s *Session, payload []byte) error {
|
||||
break
|
||||
}
|
||||
buf = buf[n:]
|
||||
fieldNumber := tag >> 3
|
||||
wireType := tag & 0x7
|
||||
if fieldNumber == 12 && wireType == 0 {
|
||||
fieldNum := tag >> 3
|
||||
if wireType == 0 {
|
||||
v, n2 := readUvarint(buf)
|
||||
if n2 == 0 {
|
||||
break
|
||||
if n2 > 0 {
|
||||
buf = buf[n2:]
|
||||
Log(fmt.Sprintf("[EX-RANK] field %d = %d", fieldNum, v))
|
||||
if v >= 100000 || (v >= 1000 && v < 10000 && parsedVal == 0) {
|
||||
parsedVal = uint32(v)
|
||||
}
|
||||
continue
|
||||
}
|
||||
buf = buf[n2:]
|
||||
groupID = uint32(v)
|
||||
break
|
||||
} else if wireType == 0 {
|
||||
_, n2 := readUvarint(buf)
|
||||
if n2 == 0 {
|
||||
break
|
||||
}
|
||||
skipWireField(uint32(wireType), &buf)
|
||||
}
|
||||
|
||||
var avatarID uint32
|
||||
if parsedVal >= 100000 {
|
||||
avatarID = parsedVal / 100 // e.g. 120401 -> 1204, 121301 -> 1213, 130801 -> 1308
|
||||
} else if parsedVal >= 1000 && parsedVal < 10000 {
|
||||
avatarID = parsedVal
|
||||
}
|
||||
|
||||
Log(fmt.Sprintf("[EX-RANK] Target avatarID: %d (from val: %d)", avatarID, parsedVal))
|
||||
|
||||
player := s.JSON()
|
||||
if player != nil {
|
||||
if avatarID == 0 {
|
||||
// Fallback: unlock for all avatars that have ExRank defined (1204, 1213, 1308)
|
||||
for aid := range common.AvatarExRankMap {
|
||||
if av, ok := player.Avatars[aid]; ok {
|
||||
av.ExRankUnlocked = true
|
||||
Log(fmt.Sprintf("[EX-RANK] Fallback set ExRankUnlocked=true for avatar %d", aid))
|
||||
syncNotify := &goproto.PlayerSyncScNotify{}
|
||||
buildSync(player, syncNotify, []uint32{aid}, nil, nil)
|
||||
_ = s.Send(syncNotify)
|
||||
}
|
||||
}
|
||||
buf = buf[n2:]
|
||||
} else {
|
||||
break
|
||||
if av, ok := player.Avatars[avatarID]; ok {
|
||||
av.ExRankUnlocked = true
|
||||
Log(fmt.Sprintf("[EX-RANK] Set ExRankUnlocked=true for avatar %d", avatarID))
|
||||
}
|
||||
syncNotify := &goproto.PlayerSyncScNotify{}
|
||||
buildSync(player, syncNotify, []uint32{avatarID}, nil, nil)
|
||||
_ = s.Send(syncNotify)
|
||||
}
|
||||
player.SavePersistent()
|
||||
}
|
||||
|
||||
// Send candidate response packets so client RPC callback resolves without spinning
|
||||
// Candidates in CmdAvatarType: 395 (CmdAvatarType_ENKEIJOLCNO), 354, 355, 364, 341
|
||||
for _, rspID := range []uint16{395, 354, 355, 364, 341} {
|
||||
_ = s.SendRaw(&NetPacket{CmdType: rspID, Body: []byte{}})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// challengeGroupStatsReply handles CmdGetChallengeGroupStatisticsCsReq (1775/1711)
|
||||
// and returns GetChallengeGroupStatisticsScRsp (1708) using standard 4.6.51 proto.
|
||||
func challengeGroupStatsReply(s *Session, payload []byte) error {
|
||||
groupID := uint32(100)
|
||||
var req goproto.GetChallengeGroupStatisticsCsReq
|
||||
if err := proto.Unmarshal(payload, &req); err == nil && req.GroupId != 0 {
|
||||
groupID = req.GroupId
|
||||
} else {
|
||||
buf := payload
|
||||
for len(buf) > 0 {
|
||||
tag, n := readUvarint(buf)
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
buf = buf[n:]
|
||||
fieldNumber := tag >> 3
|
||||
wireType := tag & 0x7
|
||||
if (fieldNumber == 5 || fieldNumber == 12) && wireType == 0 {
|
||||
v, n2 := readUvarint(buf)
|
||||
if n2 > 0 {
|
||||
groupID = uint32(v)
|
||||
break
|
||||
}
|
||||
}
|
||||
skipWireField(uint32(wireType), &buf)
|
||||
}
|
||||
}
|
||||
|
||||
var body []byte
|
||||
// tag 9: group_id
|
||||
body = append(body, 0x48)
|
||||
body = appendUvarint(body, uint64(groupID))
|
||||
// tag 15: retcode 0
|
||||
body = append(body, 0x78, 0x00)
|
||||
|
||||
switch {
|
||||
case groupID >= 2000 && groupID < 3000:
|
||||
// Pure Fiction: tag 8 = challenge_story (ChallengeStoryStatistics)
|
||||
var eik []byte
|
||||
eik = append(eik, 0x50) // tag 10: score_id 80000
|
||||
eik = appendUvarint(eik, 80000)
|
||||
eik = append(eik, 0x58) // tag 11: level 4
|
||||
eik = appendUvarint(eik, 4)
|
||||
|
||||
var css []byte
|
||||
css = append(css, 0x32) // tag 6
|
||||
css = appendUvarint(css, uint64(len(eik)))
|
||||
css = append(css, eik...)
|
||||
css = append(css, 0x38) // tag 7: record_id 1
|
||||
css = appendUvarint(css, 1)
|
||||
|
||||
body = append(body, 0x42) // tag 8
|
||||
body = appendUvarint(body, uint64(len(css)))
|
||||
body = append(body, css...)
|
||||
case groupID >= 1000 && groupID < 2000:
|
||||
// Memory of Chaos: tag 2 = challenge_default (ChallengeStatistics)
|
||||
var adk []byte
|
||||
adk = append(adk, 0x10) // tag 2: round_count 20
|
||||
adk = appendUvarint(adk, 20)
|
||||
adk = append(adk, 0x18) // tag 3: level 12
|
||||
adk = appendUvarint(adk, 12)
|
||||
|
||||
var cs []byte
|
||||
cs = append(cs, 0x32) // tag 6
|
||||
cs = appendUvarint(cs, uint64(len(adk)))
|
||||
cs = append(cs, adk...)
|
||||
cs = append(cs, 0x50) // tag 10: record_id 1
|
||||
cs = appendUvarint(cs, 1)
|
||||
|
||||
body = append(body, 0x12) // tag 2
|
||||
body = appendUvarint(body, uint64(len(cs)))
|
||||
body = append(body, cs...)
|
||||
case groupID >= 3000:
|
||||
// Apocalyptic Shadow: tag 11 = challenge_boss (ChallengeBossStatistics)
|
||||
var aan []byte
|
||||
aan = append(aan, 0x50) // tag 10: score_id 8000
|
||||
aan = appendUvarint(aan, 8000)
|
||||
aan = append(aan, 0x18) // tag 3: level 4
|
||||
aan = appendUvarint(aan, 4)
|
||||
|
||||
var cbs []byte
|
||||
cbs = append(cbs, 0x0A) // tag 1
|
||||
cbs = appendUvarint(cbs, uint64(len(aan)))
|
||||
cbs = append(cbs, aan...)
|
||||
cbs = append(cbs, 0x70) // tag 14: record_id 1
|
||||
cbs = appendUvarint(cbs, 1)
|
||||
|
||||
body = append(body, 0x5A) // tag 11
|
||||
body = appendUvarint(body, uint64(len(cbs)))
|
||||
body = append(body, cbs...)
|
||||
rsp := &goproto.GetChallengeGroupStatisticsScRsp{
|
||||
GroupId: groupID,
|
||||
Retcode: 0,
|
||||
}
|
||||
|
||||
switch {
|
||||
case groupID >= 3000:
|
||||
// Apocalyptic Shadow: challenge_boss (field 1)
|
||||
rsp.ChallengeBoss = &goproto.ChallengeBossStatistics{
|
||||
RecordId: 1,
|
||||
PPBHLLOJNEK: &goproto.AANLJBLOOFO{
|
||||
Level: 4,
|
||||
ScoreId: 8000,
|
||||
},
|
||||
}
|
||||
case groupID >= 2000 && groupID < 3000:
|
||||
// Pure Fiction: challenge_story (field 3)
|
||||
rsp.ChallengeStory = &goproto.ChallengeStoryStatistics{
|
||||
RecordId: 1,
|
||||
PPBHLLOJNEK: &goproto.EIKPHEMHIOH{
|
||||
ScoreId: 80000,
|
||||
},
|
||||
}
|
||||
case groupID >= 1000 && groupID < 2000:
|
||||
// Memory of Chaos: challenge_default (field 11)
|
||||
rsp.ChallengeDefault = &goproto.ChallengeStatistics{
|
||||
RecordId: 1,
|
||||
PPBHLLOJNEK: &goproto.ADKJKMKBFDC{
|
||||
RoundCount: 20,
|
||||
Level: 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
body, err := proto.Marshal(rsp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.SendRaw(&NetPacket{CmdType: 1708, Body: body})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user