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" "github.com/spf13/viper"
) )
type Mode string type Mode int
const ( const (
ZZ Mode = "ZZ" S1 Mode = iota + 1
Z2 Mode = "Z2" S15
Z1 Mode = "Z1" 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 { func (m Mode) String() string {
return string(m) return versionStrings[m]
} }
// Config holds the global server-wide config. // Config holds the global server-wide config.
@@ -35,7 +77,8 @@ type Config struct {
PatchServerFile string // File patch server override PatchServerFile string // File patch server override
ScreenshotAPIURL string // Destination for screenshots uploaded to BBS ScreenshotAPIURL string // Destination for screenshots uploaded to BBS
DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion
ClientMode Mode ClientMode string
RealClientMode Mode
DevMode bool DevMode bool
DevModeOptions DevModeOptions DevModeOptions DevModeOptions
@@ -225,13 +268,18 @@ func LoadConfig() (*Config, error) {
c.Host = getOutboundIP4().To4().String() c.Host = getOutboundIP4().To4().String()
} }
switch strings.ToUpper(c.ClientMode.String()) { for i := range versionStrings {
case "Z1": if strings.ToUpper(c.ClientMode) == versionStrings[i] {
c.ClientMode = Z1 c.RealClientMode = Mode(i + 1)
case "Z2": c.ClientMode = strings.ToUpper(c.ClientMode)
c.ClientMode = Z2 if c.RealClientMode < Z1 {
default: c.ClientMode += " (Debug only)"
c.ClientMode = ZZ }
}
}
if c.RealClientMode == 0 {
c.ClientMode = versionStrings[len(versionStrings)-1]
c.RealClientMode = ZZ
} }
return c, nil return c, nil

View File

@@ -56,7 +56,7 @@ func main() {
logger := zapLogger.Named("main") logger := zapLogger.Named("main")
logger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit())) 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 == "" { if config.Database.Password == "" {
preventClose("Database password is blank") 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.World = bf.ReadUint8()
m.Counter = bf.ReadUint16() m.Counter = bf.ReadUint16()
m.Offset = bf.ReadUint16() m.Offset = bf.ReadUint16()
if _config.ErupeConfig.ClientMode != _config.Z1 { if _config.ErupeConfig.RealClientMode > _config.Z1 {
m.Unk4 = bf.ReadUint8() m.Unk4 = bf.ReadUint8()
} }
return nil return nil

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,7 @@ package channelserver
import ( import (
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
_config "erupe-ce/config"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"erupe-ce/server/channelserver/compression/deltacomp" "erupe-ce/server/channelserver/compression/deltacomp"
"erupe-ce/server/channelserver/compression/nullcomp" "erupe-ce/server/channelserver/compression/nullcomp"
@@ -54,15 +55,17 @@ func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
const NaviLength = 552
func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi) pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi)
naviLength := 552
if s.server.erupeConfig.RealClientMode <= _config.G7 {
naviLength = 280
}
var data []byte var data []byte
err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data)
if len(data) == 0 { if len(data) == 0 {
s.logger.Error("Failed to load hunternavi", zap.Error(err)) s.logger.Error("Failed to load hunternavi", zap.Error(err))
data = make([]byte, NaviLength) data = make([]byte, naviLength)
} }
doAckBufSucceed(s, pkt.AckHandle, data) doAckBufSucceed(s, pkt.AckHandle, data)
} }
@@ -70,6 +73,10 @@ func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi) pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi)
if pkt.IsDataDiff { if pkt.IsDataDiff {
naviLength := 552
if s.server.erupeConfig.RealClientMode <= _config.G7 {
naviLength = 280
}
var data []byte var data []byte
// Load existing save // Load existing save
err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) 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. // 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. // This is requried as the client will try to send a diff after character creation without a prior MsgMhfSaveHunterNavi packet.
if len(data) == 0 { if len(data) == 0 {
data = make([]byte, NaviLength) data = make([]byte, naviLength)
} }
// Perform diff and compress it to write back to db // 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 { for serverIdx, si := range serverInfos {
// Prevent MezFes Worlds displaying on Z1 // Prevent MezFes Worlds displaying on Z1
if config.ClientMode == _config.Z1 { if config.RealClientMode <= _config.Z1 {
if si.Type == 6 { if si.Type == 6 {
continue continue
} }
} }
if config.RealClientMode <= _config.G6 {
if si.Type == 5 {
continue
}
}
sid := (4096 + serverIdx*256) + 16 sid := (4096 + serverIdx*256) + 16
err := s.db.QueryRow("SELECT season FROM servers WHERE server_id=$1", sid).Scan(&season) err := s.db.QueryRow("SELECT season FROM servers WHERE server_id=$1", sid).Scan(&season)
if err != nil { if err != nil {
@@ -49,10 +54,19 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
bf.WriteUint8(si.Type) bf.WriteUint8(si.Type)
bf.WriteUint8(season) bf.WriteUint8(season)
bf.WriteUint8(si.Recommended) bf.WriteUint8(si.Recommended)
bf.WriteUint8(0) // Prevents malformed server name
combined := append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...) if s.erupeConfig.RealClientMode <= _config.GG {
combined = append(combined, stringsupport.UTF8ToSJIS(si.Description)...) bf.WriteUint8(64) // Prevents malformed server name
bf.WriteBytes(stringsupport.PaddedString(string(combined), 65, false)) 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) bf.WriteUint32(si.AllowedClientFlags)
for channelIdx, ci := range si.Channels { for channelIdx, ci := range si.Channels {
@@ -101,13 +115,22 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte {
serverInfos := config.Entrance.Entries serverInfos := config.Entrance.Entries
// Decrease by the number of MezFes Worlds // Decrease by the number of MezFes Worlds
var mf int var mf int
if config.ClientMode == _config.Z1 { if config.RealClientMode <= _config.Z1 {
for _, si := range serverInfos { for _, si := range serverInfos {
if si.Type == 6 { if si.Type == 6 {
mf++ 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) rawServerData := encodeServerInfo(config, s, local)
if s.erupeConfig.DevMode && s.erupeConfig.DevModeOptions.LogOutboundMessages { 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 := 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() return bf.Data()
} }

View File

@@ -5,6 +5,7 @@ import (
ps "erupe-ce/common/pascalstring" ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
"erupe-ce/common/token" "erupe-ce/common/token"
_config "erupe-ce/config"
"erupe-ce/server/channelserver" "erupe-ce/server/channelserver"
"fmt" "fmt"
"go.uber.org/zap" "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.WriteBool(true) // Use uint16 GR, no reason not to
bf.WriteBytes(stringsupport.PaddedString(char.Name, 16, true)) // Character name bf.WriteBytes(stringsupport.PaddedString(char.Name, 16, true)) // Character name
bf.WriteBytes(stringsupport.PaddedString(char.UnkDescString, 32, false)) // unk str bf.WriteBytes(stringsupport.PaddedString(char.UnkDescString, 32, false)) // unk str
bf.WriteUint16(char.GR) if s.server.erupeConfig.RealClientMode >= _config.G7 {
bf.WriteUint16(0) // Unk bf.WriteUint16(char.GR)
bf.WriteUint8(0) // Unk
bf.WriteUint8(0) // Unk
}
} }
friends := s.server.getFriendsForCharacters(chars) friends := s.server.getFriendsForCharacters(chars)