add support for more versions

This commit is contained in:
wish
2023-07-03 00:30:44 +10:00
parent b7f9751787
commit 1f93419cb7
11 changed files with 120 additions and 35 deletions

View File

@@ -11,16 +11,58 @@ import (
"github.com/spf13/viper"
)
type Mode string
type Mode int
const (
ZZ Mode = "ZZ"
Z2 Mode = "Z2"
Z1 Mode = "Z1"
S1 Mode = iota + 1
S15
S2
S25
S3
S35
S4
S5
S55
S6
S7
S8
S85
S9
S10
F1
F2
F3
F4
F5
G1
G2
G3
G31
G32
GG
G5
G51
G52
G6
G61
G7
G8
G81
G9
G91
G10
G101
Z1
Z2
ZZ
)
var versionStrings = []string{"S1.0", "S1.5", "S2.0", "S2.5", "S3.0", "S3.5", "S4.0", "S5.0", "S5.5", "S6.0", "S7.0",
"S8.0", "S8.5", "S9", "S10", "FW.1", "FW.2", "FW.3", "FW.4", "FW.5", "G1", "G2", "G3", "G3.1", "G3.2", "GG", "G5",
"G5.1", "G5.2", "G6", "G6.1", "G7", "G8", "G8.1", "G9", "G9.1", "G10", "G10.1", "Z1", "Z2", "ZZ"}
func (m Mode) String() string {
return string(m)
return versionStrings[m]
}
// Config holds the global server-wide config.
@@ -35,7 +77,8 @@ type Config struct {
PatchServerFile string // File patch server override
ScreenshotAPIURL string // Destination for screenshots uploaded to BBS
DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion
ClientMode Mode
ClientMode string
RealClientMode Mode
DevMode bool
DevModeOptions DevModeOptions
@@ -225,13 +268,18 @@ func LoadConfig() (*Config, error) {
c.Host = getOutboundIP4().To4().String()
}
switch strings.ToUpper(c.ClientMode.String()) {
case "Z1":
c.ClientMode = Z1
case "Z2":
c.ClientMode = Z2
default:
c.ClientMode = ZZ
for i := range versionStrings {
if strings.ToUpper(c.ClientMode) == versionStrings[i] {
c.RealClientMode = Mode(i + 1)
c.ClientMode = strings.ToUpper(c.ClientMode)
if c.RealClientMode < Z1 {
c.ClientMode += " (Debug only)"
}
}
}
if c.RealClientMode == 0 {
c.ClientMode = versionStrings[len(versionStrings)-1]
c.RealClientMode = ZZ
}
return c, nil

View File

@@ -56,7 +56,7 @@ func main() {
logger := zapLogger.Named("main")
logger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit()))
logger.Info(fmt.Sprintf("Client Mode: %s", config.ClientMode.String()))
logger.Info(fmt.Sprintf("Client Mode: %s (%d)", config.ClientMode, config.RealClientMode))
if config.Database.Password == "" {
preventClose("Database password is blank")

View File

@@ -31,7 +31,7 @@ func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli
m.World = bf.ReadUint8()
m.Counter = bf.ReadUint16()
m.Offset = bf.ReadUint16()
if _config.ErupeConfig.ClientMode != _config.Z1 {
if _config.ErupeConfig.RealClientMode > _config.Z1 {
m.Unk4 = bf.ReadUint8()
}
return nil

View File

@@ -35,7 +35,7 @@ func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli
m.GR = bf.ReadUint16()
m.Stamps = bf.ReadUint16()
_ = bf.ReadUint16()
if _config.ErupeConfig.ClientMode != _config.Z1 {
if _config.ErupeConfig.RealClientMode > _config.Z1 {
m.Reward1 = uint16(bf.ReadUint32())
m.Reward2 = uint16(bf.ReadUint32())
m.Item1 = uint16(bf.ReadUint32())

View File

@@ -148,7 +148,7 @@ func (save *CharacterSaveData) Decompress() error {
func (save *CharacterSaveData) updateSaveDataWithStruct() {
rpBytes := make([]byte, 2)
binary.LittleEndian.PutUint16(rpBytes, save.RP)
if _config.ErupeConfig.ClientMode == _config.ZZ {
if _config.ErupeConfig.RealClientMode == _config.ZZ {
copy(save.decompSave[pointerRP:pointerRP+2], rpBytes)
copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF)
} else {
@@ -166,7 +166,7 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
save.Gender = false
}
if !save.IsNewCharacter {
if _config.ErupeConfig.ClientMode == _config.ZZ {
if _config.ErupeConfig.RealClientMode == _config.ZZ {
save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2])
save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5]
save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195]

View File

@@ -72,7 +72,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
var timestamps []uint32
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.DivaEvent >= 0 {
if s.server.erupeConfig.DevModeOptions.DivaEvent == 0 {
if s.server.erupeConfig.ClientMode == _config.Z1 {
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32))
} else {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
@@ -84,7 +84,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
timestamps = generateDivaTimestamps(s, start, false)
}
if s.server.erupeConfig.ClientMode != _config.Z1 {
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
bf.WriteUint32(id)
}
for i := range timestamps {

View File

@@ -92,9 +92,12 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
func generateFeatureWeapons(count int) activeFeature {
max := 14
if _config.ErupeConfig.ClientMode != _config.ZZ {
if _config.ErupeConfig.RealClientMode < _config.ZZ {
max = 13
}
if _config.ErupeConfig.RealClientMode < _config.GG {
max = 12
}
if count > max {
count = max
}

View File

@@ -1391,7 +1391,7 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint32(member.CharID)
bf.WriteUint16(member.HRP)
bf.WriteUint16(member.GR)
if s.server.erupeConfig.ClientMode != _config.ZZ {
if s.server.erupeConfig.RealClientMode < _config.ZZ {
// Magnet Spike crash workaround
bf.WriteUint16(0)
} else {

View File

@@ -3,6 +3,7 @@ package channelserver
import (
"erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
_config "erupe-ce/config"
"erupe-ce/network/mhfpacket"
"erupe-ce/server/channelserver/compression/deltacomp"
"erupe-ce/server/channelserver/compression/nullcomp"
@@ -54,15 +55,17 @@ func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
const NaviLength = 552
func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi)
naviLength := 552
if s.server.erupeConfig.RealClientMode <= _config.G7 {
naviLength = 280
}
var data []byte
err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data)
if len(data) == 0 {
s.logger.Error("Failed to load hunternavi", zap.Error(err))
data = make([]byte, NaviLength)
data = make([]byte, naviLength)
}
doAckBufSucceed(s, pkt.AckHandle, data)
}
@@ -70,6 +73,10 @@ func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi)
if pkt.IsDataDiff {
naviLength := 552
if s.server.erupeConfig.RealClientMode <= _config.G7 {
naviLength = 280
}
var data []byte
// Load existing save
err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data)
@@ -80,7 +87,7 @@ func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
// Check if we actually had any hunternavi data, using a blank buffer if not.
// This is requried as the client will try to send a diff after character creation without a prior MsgMhfSaveHunterNavi packet.
if len(data) == 0 {
data = make([]byte, NaviLength)
data = make([]byte, naviLength)
}
// Perform diff and compress it to write back to db

View File

@@ -25,11 +25,16 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
for serverIdx, si := range serverInfos {
// Prevent MezFes Worlds displaying on Z1
if config.ClientMode == _config.Z1 {
if config.RealClientMode <= _config.Z1 {
if si.Type == 6 {
continue
}
}
if config.RealClientMode <= _config.G6 {
if si.Type == 5 {
continue
}
}
sid := (4096 + serverIdx*256) + 16
err := s.db.QueryRow("SELECT season FROM servers WHERE server_id=$1", sid).Scan(&season)
if err != nil {
@@ -49,10 +54,19 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
bf.WriteUint8(si.Type)
bf.WriteUint8(season)
bf.WriteUint8(si.Recommended)
bf.WriteUint8(0) // Prevents malformed server name
combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...)
combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...)
bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false))
if s.erupeConfig.RealClientMode <= _config.GG {
bf.WriteUint8(64) // Prevents malformed server name
combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...)
combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...)
bf.WriteBytes(stringsupport.PaddedString(string(combined), 64, false))
} else {
bf.WriteUint8(0) // Prevents malformed server name
combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...)
combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...)
bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false))
}
bf.WriteUint32(si.AllowedClientFlags)
for channelIdx, ci := range si.Channels {
@@ -101,13 +115,22 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte {
serverInfos := config.Entrance.Entries
// Decrease by the number of MezFes Worlds
var mf int
if config.ClientMode == _config.Z1 {
if config.RealClientMode <= _config.Z1 {
for _, si := range serverInfos {
if si.Type == 6 {
mf++
}
}
}
// and Return Worlds
var ret int
if config.RealClientMode <= _config.G6 {
for _, si := range serverInfos {
if si.Type == 5 {
ret++
}
}
}
rawServerData := encodeServerInfo(config, s, local)
if s.erupeConfig.DevMode && s.erupeConfig.DevModeOptions.LogOutboundMessages {
@@ -115,7 +138,7 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte {
}
bf := byteframe.NewByteFrame()
bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-mf), 0x00))
bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-(mf+ret)), 0x00))
return bf.Data()
}

View File

@@ -5,6 +5,7 @@ import (
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport"
"erupe-ce/common/token"
_config "erupe-ce/config"
"erupe-ce/server/channelserver"
"fmt"
"go.uber.org/zap"
@@ -77,8 +78,11 @@ func (s *Session) makeSignResponse(uid int) []byte {
bf.WriteBool(true) // Use uint16 GR, no reason not to
bf.WriteBytes(stringsupport.PaddedString(char.Name, 16, true)) // Character name
bf.WriteBytes(stringsupport.PaddedString(char.UnkDescString, 32, false)) // unk str
bf.WriteUint16(char.GR)
bf.WriteUint16(0) // Unk
if s.server.erupeConfig.RealClientMode >= _config.G7 {
bf.WriteUint16(char.GR)
bf.WriteUint8(0) // Unk
bf.WriteUint8(0) // Unk
}
}
friends := s.server.getFriendsForCharacters(chars)