various Tower changes

This commit is contained in:
wish
2023-06-11 18:51:56 +10:00
parent f69aebc9da
commit 2c8391b5a4
7 changed files with 225 additions and 72 deletions

View File

@@ -2,6 +2,7 @@ package stringsupport
import (
"bytes"
"fmt"
"io"
"strconv"
"strings"
@@ -96,3 +97,23 @@ func CSVElems(csv string) []int {
}
return r
}
func CSVGetIndex(csv string, i int) int {
s := CSVElems(csv)
if i < len(s) {
return s[i]
}
return 0
}
func CSVSetIndex(csv string, i int, v int) string {
s := CSVElems(csv)
if i < len(s) {
s[i] = v
}
var r []string
for j := 0; j < len(s); j++ {
r = append(r, fmt.Sprintf(`%d`, s[j]))
}
return strings.Join(r, ",")
}

View File

@@ -8,19 +8,8 @@ import (
"erupe-ce/network/clientctx"
)
// The server sends different responses based on these values.
const (
TowerInfoTypeUnk0 = iota
TowerInfoTypeTowerRankPoint
TowerInfoTypeGetOwnTowerSkill
TowerInfoTypeGetOwnTowerLevelV3
TowerInfoTypeTowerTouhaHistory
TowerInfoTypeUnk5
)
// MsgMhfGetTowerInfo represents the MSG_MHF_GET_TOWER_INFO
type MsgMhfGetTowerInfo struct {
// Communicator type, multi-format. This might be valid for only one type.
AckHandle uint32
InfoType uint32 // Requested response type
Unk0 uint32

View File

@@ -1,15 +1,24 @@
package mhfpacket
import (
"errors"
import (
"errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
// MsgMhfPostGemInfo represents the MSG_MHF_POST_GEM_INFO
type MsgMhfPostGemInfo struct{}
type MsgMhfPostGemInfo struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
Unk2 int32
Unk3 int32
Unk4 int32
Unk5 int32
Unk6 int32
}
// Opcode returns the ID associated with this packet type.
func (m *MsgMhfPostGemInfo) Opcode() network.PacketID {
@@ -18,7 +27,15 @@ func (m *MsgMhfPostGemInfo) Opcode() network.PacketID {
// Parse parses the packet from binary
func (m *MsgMhfPostGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
return errors.New("NOT IMPLEMENTED")
m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint32()
m.Unk1 = bf.ReadUint32()
m.Unk2 = bf.ReadInt32()
m.Unk3 = bf.ReadInt32()
m.Unk4 = bf.ReadInt32()
m.Unk5 = bf.ReadInt32()
m.Unk6 = bf.ReadInt32()
return nil
}
// Build builds a binary packet from the current data.

View File

@@ -1,28 +1,26 @@
package mhfpacket
import (
"errors"
import (
"errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
// MsgMhfPostTowerInfo represents the MSG_MHF_POST_TOWER_INFO
type MsgMhfPostTowerInfo struct {
// Communicator type, multi-format. This might be valid for only one type.
AckHandle uint32
Unk0 uint32
InfoType uint32
Unk1 uint32
Unk2 uint32
Unk3 uint32
Unk4 uint32
Unk5 uint32
Unk6 uint32
Unk7 uint32
Unk8 uint32
Unk9 uint32
Unk10 uint32
Unk2 int32
Unk3 int32
Unk4 int32
Unk5 int32
Unk6 int32
Unk7 int32
Unk8 int32
Unk9 int64
}
// Opcode returns the ID associated with this packet type.
@@ -33,17 +31,16 @@ func (m *MsgMhfPostTowerInfo) Opcode() network.PacketID {
// Parse parses the packet from binary
func (m *MsgMhfPostTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint32()
m.InfoType = bf.ReadUint32()
m.Unk1 = bf.ReadUint32()
m.Unk2 = bf.ReadUint32()
m.Unk3 = bf.ReadUint32()
m.Unk4 = bf.ReadUint32()
m.Unk5 = bf.ReadUint32()
m.Unk6 = bf.ReadUint32()
m.Unk7 = bf.ReadUint32()
m.Unk8 = bf.ReadUint32()
m.Unk9 = bf.ReadUint32()
m.Unk10 = bf.ReadUint32()
m.Unk2 = bf.ReadInt32()
m.Unk3 = bf.ReadInt32()
m.Unk4 = bf.ReadInt32()
m.Unk5 = bf.ReadInt32()
m.Unk6 = bf.ReadInt32()
m.Unk7 = bf.ReadInt32()
m.Unk8 = bf.ReadInt32()
m.Unk9 = bf.ReadInt64()
return nil
}

12
patch-schema/tower.sql Normal file
View File

@@ -0,0 +1,12 @@
BEGIN;
CREATE TABLE IF NOT EXISTS tower (
char_id INT,
tr INT,
trp INT,
tsp INT,
zone1 INT,
skills TEXT DEFAULT '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0'
);
END;

View File

@@ -27,17 +27,6 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) {
doAckBufSucceed(s, ackHandle, enumBf.Data())
}
// Temporary function to just return no results for many MSG_MHF_GET* packets.
func stubGetNoResults(s *Session, ackHandle uint32) {
resp := byteframe.NewByteFrame()
resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. (World ID?)
resp.WriteUint32(0) // Unk
resp.WriteUint32(0) // Unk
resp.WriteUint32(0) // Entry count
doAckBufSucceed(s, ackHandle, resp.Data())
}
func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride))

View File

@@ -1,46 +1,97 @@
package channelserver
import (
"encoding/hex"
"erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket"
)
type TowerInfoTRP struct {
TR int32
TRP int32
}
type TowerInfoSkill struct {
TSP int32
Unk1 []int16 // 40
}
type TowerInfoHistory struct {
Unk0 []int16 // 5
Unk1 []int16 // 5
}
type TowerInfoLevel struct {
Zone1 int32
Unk1 int32
Unk2 int32
Unk3 int32
}
func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetTowerInfo)
var data []*byteframe.ByteFrame
type TowerInfo struct {
TRP []uint64
TowerSkill [][]byte // 132 bytes
TowerHistory [][]byte // 20 bytes
TRP []TowerInfoTRP
Skill []TowerInfoSkill
History []TowerInfoHistory
Level []TowerInfoLevel
}
towerInfo := TowerInfo{
TRP: []uint64{0},
TowerSkill: [][]byte{make([]byte, 132)},
TowerHistory: [][]byte{make([]byte, 20)},
TRP: []TowerInfoTRP{{0, 0}},
Skill: []TowerInfoSkill{{0, make([]int16, 40)}},
History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}},
Level: []TowerInfoLevel{{0, 0, 0, 0}},
}
// Example data
// towerInfo.TowerSkill[0], _ = hex.DecodeString("0000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
tempSkills := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(zone1, 0), skills FROM tower WHERE char_id=$1
`, s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Zone1, &tempSkills)
if err != nil {
s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID)
}
for i, skill := range stringsupport.CSVElems(tempSkills) {
towerInfo.Skill[0].Unk1[i] = int16(skill)
}
switch pkt.InfoType {
case 1:
for _, trp := range towerInfo.TRP {
bf := byteframe.NewByteFrame()
bf.WriteUint64(trp)
bf.WriteInt32(trp.TR)
bf.WriteInt32(trp.TRP)
data = append(data, bf)
}
case 2:
for _, skills := range towerInfo.TowerSkill {
for _, skills := range towerInfo.Skill {
bf := byteframe.NewByteFrame()
bf.WriteBytes(skills)
bf.WriteInt32(skills.TSP)
for i := range skills.Unk1 {
bf.WriteInt16(skills.Unk1[i])
}
data = append(data, bf)
}
case 4:
for _, history := range towerInfo.TowerHistory {
for _, history := range towerInfo.History {
bf := byteframe.NewByteFrame()
bf.WriteBytes(history)
for i := range history.Unk0 {
bf.WriteInt16(history.Unk0[i])
}
for i := range history.Unk1 {
bf.WriteInt16(history.Unk1[i])
}
data = append(data, bf)
}
case 5:
for _, level := range towerInfo.Level {
bf := byteframe.NewByteFrame()
bf.WriteInt32(level.Zone1)
bf.WriteInt32(level.Unk1)
bf.WriteInt32(level.Unk2)
bf.WriteInt32(level.Unk3)
data = append(data, bf)
}
}
@@ -49,9 +100,55 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostTowerInfo)
switch pkt.InfoType {
case 2:
skills := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills)
s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Unk2), stringsupport.CSVGetIndex(skills, int(pkt.Unk2))+1), pkt.Unk5, s.charID)
case 7:
s.server.db.Exec(`UPDATE tower SET tr=$1, trp=$2, zone1=zone1+$3 WHERE char_id=$4`, pkt.Unk3, pkt.Unk4, pkt.Unk8, s.charID)
}
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
}
type TenrouiraiCharScore struct {
Score int32
Name string
}
type TenrouiraiProgress struct {
Unk0 uint8
Unk1 uint16
Unk2 uint16
Unk3 uint16
}
type TenrouiraiTicket struct {
Unk0 uint8
Unk1 uint32
Unk2 uint32
}
type TenrouiraiData struct {
Unk0 uint8
Unk1 uint8
Unk2 uint16
Unk3 uint16
Unk4 uint8
Unk5 uint8
Unk6 uint8
Unk7 uint8
Unk8 uint8
Unk9 uint8
}
type Tenrouirai struct {
CharScore []TenrouiraiCharScore
Progress []TenrouiraiProgress
Ticket []TenrouiraiTicket
Data []TenrouiraiData
}
func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
// if the game gets bad responses for this it breaks the ability to save
pkt := p.(*mhfpacket.MsgMhfGetTenrouirai)
@@ -125,14 +222,45 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) {
doAckEarthSucceed(s, pkt.AckHandle, data)
}
type GemInfo struct {
Unk0 uint16
Unk1 uint16
}
type GemHistory struct {
Unk0 uint16
Unk1 uint16
Unk2 uint32
Unk3 string
}
func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetGemInfo)
var data []*byteframe.ByteFrame
/*
bf.WriteUint16(0)
bf.WriteUint16(0)
*/
gemInfo := []GemInfo{}
gemHistory := []GemHistory{}
switch pkt.Unk0 {
case 1:
for _, history := range gemHistory {
bf := byteframe.NewByteFrame()
bf.WriteUint16(history.Unk0)
bf.WriteUint16(history.Unk1)
bf.WriteUint32(history.Unk2)
bf.WriteBytes(stringsupport.PaddedString(history.Unk3, 14, true))
data = append(data, bf)
}
default:
for _, info := range gemInfo {
bf := byteframe.NewByteFrame()
bf.WriteUint16(info.Unk0)
bf.WriteUint16(info.Unk1)
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
}
func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostGemInfo)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}