Merge pull request #72 from ZeruLight/fix/dynamic-tune-vals

dynamic tune values
This commit is contained in:
wish
2023-07-01 23:59:57 +10:00
committed by GitHub
45 changed files with 3176 additions and 501 deletions

View File

@@ -2,6 +2,7 @@ package stringsupport
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"strconv" "strconv"
"strings" "strings"
@@ -96,3 +97,23 @@ func CSVElems(csv string) []int {
} }
return r 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

@@ -11,6 +11,7 @@
"PatchServerFile": "", "PatchServerFile": "",
"ScreenshotAPIURL": "", "ScreenshotAPIURL": "",
"DeleteOnSaveCorruption": false, "DeleteOnSaveCorruption": false,
"ClientMode": "ZZ",
"DevMode": true, "DevMode": true,
"DevModeOptions": { "DevModeOptions": {
"AutoCreateAccount": true, "AutoCreateAccount": true,
@@ -27,6 +28,8 @@
"DisableTokenCheck": false, "DisableTokenCheck": false,
"QuestDebugTools": false, "QuestDebugTools": false,
"EarthStatusOverride": 0, "EarthStatusOverride": 0,
"EarthIDOverride": 0,
"EarthMonsterOverride": 0,
"SaveDumps": { "SaveDumps": {
"Enabled": true, "Enabled": true,
"OutputDir": "savedata" "OutputDir": "savedata"
@@ -43,7 +46,18 @@
"BonusQuestAllowance": 3, "BonusQuestAllowance": 3,
"DailyQuestAllowance": 1, "DailyQuestAllowance": 1,
"MezfesSoloTickets": 10, "MezfesSoloTickets": 10,
"MezfesGroupTickets": 4 "MezfesGroupTickets": 4,
"GUrgentRate": 10,
"GCPMultiplier": 1.00,
"GRPMultiplier": 1.00,
"GSRPMultiplier": 1.00,
"GZennyMultiplier": 1.00,
"MaterialMultiplier": 1.00,
"ExtraCarves": 0,
"DisableHunterNavi": false,
"EnableHiganjimaEvent": false,
"EnableNierEvent": false,
"DisableRoad": false
}, },
"Discord": { "Discord": {
"Enabled": false, "Enabled": false,

View File

@@ -1,15 +1,28 @@
package config package _config
import ( import (
"fmt" "fmt"
"log" "log"
"net" "net"
"os" "os"
"strings"
"time" "time"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type Mode string
const (
ZZ Mode = "ZZ"
Z2 Mode = "Z2"
Z1 Mode = "Z1"
)
func (m Mode) String() string {
return string(m)
}
// Config holds the global server-wide config. // Config holds the global server-wide config.
type Config struct { type Config struct {
Host string `mapstructure:"Host"` Host string `mapstructure:"Host"`
@@ -22,6 +35,7 @@ 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
DevMode bool DevMode bool
DevModeOptions DevModeOptions DevModeOptions DevModeOptions
@@ -38,21 +52,23 @@ type Config struct {
// DevModeOptions holds various debug/temporary options for use while developing Erupe. // DevModeOptions holds various debug/temporary options for use while developing Erupe.
type DevModeOptions struct { type DevModeOptions struct {
AutoCreateAccount bool // Automatically create accounts if they don't exist AutoCreateAccount bool // Automatically create accounts if they don't exist
CleanDB bool // Automatically wipes the DB on server reset. CleanDB bool // Automatically wipes the DB on server reset.
MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds.
LogInboundMessages bool // Log all messages sent to the server LogInboundMessages bool // Log all messages sent to the server
LogOutboundMessages bool // Log all messages sent to the clients LogOutboundMessages bool // Log all messages sent to the clients
MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled
DivaEvent int // Diva Defense event status DivaEvent int // Diva Defense event status
FestaEvent int // Hunter's Festa event status FestaEvent int // Hunter's Festa event status
TournamentEvent int // VS Tournament event status TournamentEvent int // VS Tournament event status
MezFesEvent bool // MezFes status MezFesEvent bool // MezFes status
MezFesAlt bool // Swaps out Volpakkun for Tokotoko MezFesAlt bool // Swaps out Volpakkun for Tokotoko
DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!)
QuestDebugTools bool // Enable various quest debug logs QuestDebugTools bool // Enable various quest debug logs
EarthStatusOverride int32 EarthStatusOverride int32
SaveDumps SaveDumpOptions EarthIDOverride int32
EarthMonsterOverride int32
SaveDumps SaveDumpOptions
} }
type SaveDumpOptions struct { type SaveDumpOptions struct {
@@ -62,17 +78,28 @@ type SaveDumpOptions struct {
// GameplayOptions has various gameplay modifiers // GameplayOptions has various gameplay modifiers
type GameplayOptions struct { type GameplayOptions struct {
FeaturedWeapons int // Number of Active Feature weapons to generate daily FeaturedWeapons int // Number of Active Feature weapons to generate daily
MaximumNP int // Maximum number of NP held by a player MaximumNP int // Maximum number of NP held by a player
MaximumRP uint16 // Maximum number of RP held by a player MaximumRP uint16 // Maximum number of RP held by a player
DisableLoginBoost bool // Disables the Login Boost system DisableLoginBoost bool // Disables the Login Boost system
DisableBoostTime bool // Disables the daily NetCafe Boost Time DisableBoostTime bool // Disables the daily NetCafe Boost Time
BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for
GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking
BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily
DailyQuestAllowance uint32 // Number of Daily Quests to allow daily DailyQuestAllowance uint32 // Number of Daily Quests to allow daily
MezfesSoloTickets uint32 // Number of solo tickets given weekly MezfesSoloTickets uint32 // Number of solo tickets given weekly
MezfesGroupTickets uint32 // Number of group tickets given weekly MezfesGroupTickets uint32 // Number of group tickets given weekly
GUrgentRate uint16 // Adjusts the rate of G Urgent quests spawning
GCPMultiplier float32 // Adjusts the multiplier of GCP rewarded for quest completion
GRPMultiplier float32 // Adjusts the multiplier of G Rank Points rewarded for quest completion
GSRPMultiplier float32 // Adjusts the multiplier of G Skill Rank Points rewarded for quest completion
GZennyMultiplier float32 // Adjusts the multiplier of G Zenny rewarded for quest completion
MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion
ExtraCarves uint16 // Grant n extra chances to carve ALL carcasses
DisableHunterNavi bool // Disables the Hunter Navi
EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar
EnableNierEvent bool // Enables the Nier event in the Rasta Bar
DisableRoad bool // Disables the Hunting Road
} }
// Discord holds the discord integration config. // Discord holds the discord integration config.
@@ -157,7 +184,6 @@ func init() {
if err != nil { if err != nil {
preventClose(fmt.Sprintf("Failed to load config: %s", err.Error())) preventClose(fmt.Sprintf("Failed to load config: %s", err.Error()))
} }
} }
// getOutboundIP4 gets the preferred outbound ip4 of this machine // getOutboundIP4 gets the preferred outbound ip4 of this machine
@@ -199,6 +225,15 @@ func LoadConfig() (*Config, error) {
c.Host = getOutboundIP4().To4().String() 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
}
return c, nil return c, nil
} }

64
main.go
View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
_config "erupe-ce/config"
"fmt" "fmt"
"net" "net"
"os" "os"
@@ -9,7 +10,6 @@ import (
"syscall" "syscall"
"time" "time"
"erupe-ce/config"
"erupe-ce/server/channelserver" "erupe-ce/server/channelserver"
"erupe-ce/server/discordbot" "erupe-ce/server/discordbot"
"erupe-ce/server/entranceserver" "erupe-ce/server/entranceserver"
@@ -45,7 +45,8 @@ func main() {
var err error var err error
var zapLogger *zap.Logger var zapLogger *zap.Logger
if config.ErupeConfig.DevMode { config := _config.ErupeConfig
if config.DevMode {
zapLogger, _ = zap.NewDevelopment() zapLogger, _ = zap.NewDevelopment()
} else { } else {
zapLogger, _ = zap.NewProduction() zapLogger, _ = zap.NewProduction()
@@ -55,20 +56,21 @@ 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()))
if config.ErupeConfig.Database.Password == "" { if config.Database.Password == "" {
preventClose("Database password is blank") preventClose("Database password is blank")
} }
if net.ParseIP(config.ErupeConfig.Host) == nil { if net.ParseIP(config.Host) == nil {
ips, _ := net.LookupIP(config.ErupeConfig.Host) ips, _ := net.LookupIP(config.Host)
for _, ip := range ips { for _, ip := range ips {
if ip != nil { if ip != nil {
config.ErupeConfig.Host = ip.String() config.Host = ip.String()
break break
} }
} }
if net.ParseIP(config.ErupeConfig.Host) == nil { if net.ParseIP(config.Host) == nil {
preventClose("Invalid host address") preventClose("Invalid host address")
} }
} }
@@ -76,10 +78,10 @@ func main() {
// Discord bot // Discord bot
var discordBot *discordbot.DiscordBot = nil var discordBot *discordbot.DiscordBot = nil
if config.ErupeConfig.Discord.Enabled { if config.Discord.Enabled {
bot, err := discordbot.NewDiscordBot(discordbot.Options{ bot, err := discordbot.NewDiscordBot(discordbot.Options{
Logger: logger, Logger: logger,
Config: config.ErupeConfig, Config: _config.ErupeConfig,
}) })
if err != nil { if err != nil {
@@ -102,11 +104,11 @@ func main() {
// Create the postgres DB pool. // Create the postgres DB pool.
connectString := fmt.Sprintf( connectString := fmt.Sprintf(
"host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable",
config.ErupeConfig.Database.Host, config.Database.Host,
config.ErupeConfig.Database.Port, config.Database.Port,
config.ErupeConfig.Database.User, config.Database.User,
config.ErupeConfig.Database.Password, config.Database.Password,
config.ErupeConfig.Database.Database, config.Database.Database,
) )
db, err := sqlx.Open("postgres", connectString) db, err := sqlx.Open("postgres", connectString)
@@ -126,7 +128,7 @@ func main() {
_ = db.MustExec("DELETE FROM servers") _ = db.MustExec("DELETE FROM servers")
// Clean the DB if the option is on. // Clean the DB if the option is on.
if config.ErupeConfig.DevMode && config.ErupeConfig.DevModeOptions.CleanDB { if config.DevMode && config.DevModeOptions.CleanDB {
logger.Info("Database: Started clearing...") logger.Info("Database: Started clearing...")
cleanDB(db) cleanDB(db)
logger.Info("Database: Finished clearing") logger.Info("Database: Finished clearing")
@@ -139,11 +141,11 @@ func main() {
// Entrance server. // Entrance server.
var entranceServer *entranceserver.Server var entranceServer *entranceserver.Server
if config.ErupeConfig.Entrance.Enabled { if config.Entrance.Enabled {
entranceServer = entranceserver.NewServer( entranceServer = entranceserver.NewServer(
&entranceserver.Config{ &entranceserver.Config{
Logger: logger.Named("entrance"), Logger: logger.Named("entrance"),
ErupeConfig: config.ErupeConfig, ErupeConfig: _config.ErupeConfig,
DB: db, DB: db,
}) })
err = entranceServer.Start() err = entranceServer.Start()
@@ -158,11 +160,11 @@ func main() {
// Sign server. // Sign server.
var signServer *signserver.Server var signServer *signserver.Server
if config.ErupeConfig.Sign.Enabled { if config.Sign.Enabled {
signServer = signserver.NewServer( signServer = signserver.NewServer(
&signserver.Config{ &signserver.Config{
Logger: logger.Named("sign"), Logger: logger.Named("sign"),
ErupeConfig: config.ErupeConfig, ErupeConfig: _config.ErupeConfig,
DB: db, DB: db,
}) })
err = signServer.Start() err = signServer.Start()
@@ -176,11 +178,11 @@ func main() {
// New Sign server // New Sign server
var newSignServer *signv2server.Server var newSignServer *signv2server.Server
if config.ErupeConfig.SignV2.Enabled { if config.SignV2.Enabled {
newSignServer = signv2server.NewServer( newSignServer = signv2server.NewServer(
&signv2server.Config{ &signv2server.Config{
Logger: logger.Named("sign"), Logger: logger.Named("sign"),
ErupeConfig: config.ErupeConfig, ErupeConfig: _config.ErupeConfig,
DB: db, DB: db,
}) })
err = newSignServer.Start() err = newSignServer.Start()
@@ -194,23 +196,23 @@ func main() {
var channels []*channelserver.Server var channels []*channelserver.Server
if config.ErupeConfig.Channel.Enabled { if config.Channel.Enabled {
channelQuery := "" channelQuery := ""
si := 0 si := 0
ci := 0 ci := 0
count := 1 count := 1
for j, ee := range config.ErupeConfig.Entrance.Entries { for j, ee := range config.Entrance.Entries {
for i, ce := range ee.Channels { for i, ce := range ee.Channels {
sid := (4096 + si*256) + (16 + ci) sid := (4096 + si*256) + (16 + ci)
c := *channelserver.NewServer(&channelserver.Config{ c := *channelserver.NewServer(&channelserver.Config{
ID: uint16(sid), ID: uint16(sid),
Logger: logger.Named("channel-" + fmt.Sprint(count)), Logger: logger.Named("channel-" + fmt.Sprint(count)),
ErupeConfig: config.ErupeConfig, ErupeConfig: _config.ErupeConfig,
DB: db, DB: db,
DiscordBot: discordBot, DiscordBot: discordBot,
}) })
if ee.IP == "" { if ee.IP == "" {
c.IP = config.ErupeConfig.Host c.IP = config.Host
} else { } else {
c.IP = ee.IP c.IP = ee.IP
} }
@@ -246,7 +248,7 @@ func main() {
signal.Notify(c, os.Interrupt, syscall.SIGTERM) signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c <-c
if !config.ErupeConfig.DisableSoftCrash { if !config.DisableSoftCrash {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
message := fmt.Sprintf("Shutting down in %d...", 10-i) message := fmt.Sprintf("Shutting down in %d...", 10-i)
for _, c := range channels { for _, c := range channels {
@@ -257,21 +259,21 @@ func main() {
} }
} }
if config.ErupeConfig.Channel.Enabled { if config.Channel.Enabled {
for _, c := range channels { for _, c := range channels {
c.Shutdown() c.Shutdown()
} }
} }
if config.ErupeConfig.Sign.Enabled { if config.Sign.Enabled {
signServer.Shutdown() signServer.Shutdown()
} }
if config.ErupeConfig.SignV2.Enabled { if config.SignV2.Enabled {
newSignServer.Shutdown() newSignServer.Shutdown()
} }
if config.ErupeConfig.Entrance.Enabled { if config.Entrance.Enabled {
entranceServer.Shutdown() entranceServer.Shutdown()
} }
@@ -285,7 +287,7 @@ func wait() {
} }
func preventClose(text string) { func preventClose(text string) {
if config.ErupeConfig.DisableSoftCrash { if _config.ErupeConfig.DisableSoftCrash {
os.Exit(0) os.Exit(0)
} }
fmt.Println("\nFailed to start Erupe:\n" + text) fmt.Println("\nFailed to start Erupe:\n" + text)

View File

@@ -1,15 +1,20 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfCaravanMyRank represents the MSG_MHF_CARAVAN_MY_RANK // MsgMhfCaravanMyRank represents the MSG_MHF_CARAVAN_MY_RANK
type MsgMhfCaravanMyRank struct{} type MsgMhfCaravanMyRank struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
Unk2 uint32
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfCaravanMyRank) Opcode() network.PacketID { func (m *MsgMhfCaravanMyRank) Opcode() network.PacketID {
@@ -18,7 +23,11 @@ func (m *MsgMhfCaravanMyRank) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfCaravanMyRank) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfCaravanMyRank) 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.ReadUint32()
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

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

View File

@@ -1,15 +1,20 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfCaravanRanking represents the MSG_MHF_CARAVAN_RANKING // MsgMhfCaravanRanking represents the MSG_MHF_CARAVAN_RANKING
type MsgMhfCaravanRanking struct{} type MsgMhfCaravanRanking struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
Unk2 int32
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfCaravanRanking) Opcode() network.PacketID { func (m *MsgMhfCaravanRanking) Opcode() network.PacketID {
@@ -18,7 +23,11 @@ func (m *MsgMhfCaravanRanking) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfCaravanRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfCaravanRanking) 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()
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -2,6 +2,7 @@ package mhfpacket
import ( import (
"errors" "errors"
_config "erupe-ce/config"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network" "erupe-ce/network"
@@ -30,7 +31,9 @@ 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()
m.Unk4 = bf.ReadUint8() if _config.ErupeConfig.ClientMode != _config.Z1 {
m.Unk4 = bf.ReadUint8()
}
return nil return nil
} }

View File

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

View File

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

View File

@@ -11,8 +11,13 @@ import (
// MsgMhfGetGemInfo represents the MSG_MHF_GET_GEM_INFO // MsgMhfGetGemInfo represents the MSG_MHF_GET_GEM_INFO
type MsgMhfGetGemInfo struct { type MsgMhfGetGemInfo struct {
AckHandle uint32 AckHandle uint32
Unk uint32 Unk0 uint32
Unk1 []byte Unk1 uint32
Unk2 int32
Unk3 int32
Unk4 int32
Unk5 int32
Unk6 int32
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -23,8 +28,13 @@ func (m *MsgMhfGetGemInfo) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk = bf.ReadUint32() m.Unk0 = bf.ReadUint32()
m.Unk1 = bf.ReadBytes(24) 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 return nil
} }

View File

@@ -1,15 +1,20 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfGetNotice represents the MSG_MHF_GET_NOTICE // MsgMhfGetNotice represents the MSG_MHF_GET_NOTICE
type MsgMhfGetNotice struct{} type MsgMhfGetNotice struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
Unk2 int32
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfGetNotice) Opcode() network.PacketID { func (m *MsgMhfGetNotice) Opcode() network.PacketID {
@@ -18,7 +23,11 @@ func (m *MsgMhfGetNotice) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetNotice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetNotice) 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()
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -11,8 +11,8 @@ import (
// MsgMhfGetRyoudama represents the MSG_MHF_GET_RYOUDAMA // MsgMhfGetRyoudama represents the MSG_MHF_GET_RYOUDAMA
type MsgMhfGetRyoudama struct { type MsgMhfGetRyoudama struct {
AckHandle uint32 AckHandle uint32
Unk0 uint8 Request1 uint8
Unk1 uint8 Request2 uint8
GuildID uint32 GuildID uint32
Unk3 uint8 Unk3 uint8
} }
@@ -25,8 +25,8 @@ func (m *MsgMhfGetRyoudama) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetRyoudama) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetRyoudama) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint8() m.Request1 = bf.ReadUint8()
m.Unk1 = bf.ReadUint8() m.Request2 = bf.ReadUint8()
m.GuildID = bf.ReadUint32() m.GuildID = bf.ReadUint32()
m.Unk3 = bf.ReadUint8() m.Unk3 = bf.ReadUint8()
return nil return nil

View File

@@ -1,20 +1,19 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfGetSeibattle represents the MSG_MHF_GET_SEIBATTLE // MsgMhfGetSeibattle represents the MSG_MHF_GET_SEIBATTLE
type MsgMhfGetSeibattle struct { type MsgMhfGetSeibattle struct {
// Communicator type, multi-format. This might be valid for only one type.
AckHandle uint32 AckHandle uint32
Unk0 uint8 Unk0 uint8
Unk1 uint8 Type uint8
Unk2 uint32 // Some shared ID with MSG_SYS_RECORD_LOG, world ID? GuildID uint32
Unk3 uint8 Unk3 uint8
Unk4 uint16 Unk4 uint16
} }
@@ -28,8 +27,8 @@ func (m *MsgMhfGetSeibattle) Opcode() network.PacketID {
func (m *MsgMhfGetSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint8() m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint8() m.Type = bf.ReadUint8()
m.Unk2 = bf.ReadUint32() m.GuildID = bf.ReadUint32()
m.Unk3 = bf.ReadUint8() m.Unk3 = bf.ReadUint8()
m.Unk4 = bf.ReadUint16() m.Unk4 = bf.ReadUint16()
return nil return nil

View File

@@ -1,20 +1,21 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfGetTenrouirai represents the MSG_MHF_GET_TENROUIRAI // MsgMhfGetTenrouirai represents the MSG_MHF_GET_TENROUIRAI
type MsgMhfGetTenrouirai struct { type MsgMhfGetTenrouirai struct {
// Communicator type, multi-format. This might be valid for only one type.
AckHandle uint32 AckHandle uint32
Unk0 uint16 Unk0 uint8
Unk1 uint32 Unk1 uint8
Unk2 uint16 GuildID uint32
Unk3 uint8
Unk4 uint8
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -25,9 +26,11 @@ func (m *MsgMhfGetTenrouirai) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint16() m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint32() m.Unk1 = bf.ReadUint8()
m.Unk2 = bf.ReadUint16() m.GuildID = bf.ReadUint32()
m.Unk3 = bf.ReadUint8()
m.Unk4 = bf.ReadUint8()
return nil return nil
} }

View File

@@ -1,19 +1,20 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfGetTinyBin represents the MSG_MHF_GET_TINY_BIN // MsgMhfGetTinyBin represents the MSG_MHF_GET_TINY_BIN
type MsgMhfGetTinyBin struct { type MsgMhfGetTinyBin struct {
// Communicator type, multi-format. This might be valid for only one type. // Communicator type, multi-format. This might be valid for only one type.
AckHandle uint32 AckHandle uint32
Unk0 uint16 Unk0 uint8
Unk1 uint8 Unk1 uint8
Unk2 uint8
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -24,8 +25,9 @@ func (m *MsgMhfGetTinyBin) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint16() m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint8() m.Unk1 = bf.ReadUint8()
m.Unk2 = bf.ReadUint8()
return nil return nil
} }

View File

@@ -8,19 +8,8 @@ import (
"erupe-ce/network/clientctx" "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 // MsgMhfGetTowerInfo represents the MSG_MHF_GET_TOWER_INFO
type MsgMhfGetTowerInfo struct { type MsgMhfGetTowerInfo struct {
// Communicator type, multi-format. This might be valid for only one type.
AckHandle uint32 AckHandle uint32
InfoType uint32 // Requested response type InfoType uint32 // Requested response type
Unk0 uint32 Unk0 uint32

View File

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

View File

@@ -1,15 +1,21 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfPostNotice represents the MSG_MHF_POST_NOTICE // MsgMhfPostNotice represents the MSG_MHF_POST_NOTICE
type MsgMhfPostNotice struct{} type MsgMhfPostNotice struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
Unk2 int32
Unk3 int32
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfPostNotice) Opcode() network.PacketID { func (m *MsgMhfPostNotice) Opcode() network.PacketID {
@@ -18,7 +24,12 @@ func (m *MsgMhfPostNotice) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfPostNotice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfPostNotice) 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()
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -1,22 +1,34 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfPostTenrouirai represents the MSG_MHF_POST_TENROUIRAI // MsgMhfPostTenrouirai represents the MSG_MHF_POST_TENROUIRAI
type MsgMhfPostTenrouirai struct{ type MsgMhfPostTenrouirai struct {
AckHandle uint32 AckHandle uint32
Unk0 uint16 Unk0 uint8
Unk1 uint32 Op uint8
Unk2 uint32 GuildID uint32
Unk3 uint32 Unk1 uint8
Unk4 uint32
Unk5 uint8 Floors uint16
Antiques uint16
Chests uint16
Cats uint16
TRP uint16
Slays uint16
DonatedRP uint16
PreviousRP uint16
Unk2_0 uint16
Unk2_1 uint16
Unk2_2 uint16
Unk2_3 uint16
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -27,12 +39,28 @@ func (m *MsgMhfPostTenrouirai) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfPostTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfPostTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint16() m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint32() m.Op = bf.ReadUint8()
m.Unk2 = bf.ReadUint32() m.GuildID = bf.ReadUint32()
m.Unk3 = bf.ReadUint32() m.Unk1 = bf.ReadUint8()
m.Unk4 = bf.ReadUint32()
m.Unk5 = bf.ReadUint8() switch m.Op {
case 1:
m.Floors = bf.ReadUint16()
m.Antiques = bf.ReadUint16()
m.Chests = bf.ReadUint16()
m.Cats = bf.ReadUint16()
m.TRP = bf.ReadUint16()
m.Slays = bf.ReadUint16()
case 2:
m.DonatedRP = bf.ReadUint16()
m.PreviousRP = bf.ReadUint16()
m.Unk2_0 = bf.ReadUint16()
m.Unk2_1 = bf.ReadUint16()
m.Unk2_2 = bf.ReadUint16()
m.Unk2_3 = bf.ReadUint16()
}
return nil return nil
} }

View File

@@ -11,9 +11,10 @@ import (
// MsgMhfPostTinyBin represents the MSG_MHF_POST_TINY_BIN // MsgMhfPostTinyBin represents the MSG_MHF_POST_TINY_BIN
type MsgMhfPostTinyBin struct { type MsgMhfPostTinyBin struct {
AckHandle uint32 AckHandle uint32
Unk0 uint16 Unk0 uint8
Unk1 uint8 Unk1 uint8
Unk2 uint8 Unk2 uint8
Unk3 uint8
Data []byte Data []byte
} }
@@ -25,9 +26,10 @@ func (m *MsgMhfPostTinyBin) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfPostTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfPostTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint16() m.Unk0 = bf.ReadUint8()
m.Unk1 = bf.ReadUint8() m.Unk1 = bf.ReadUint8()
m.Unk2 = bf.ReadUint8() m.Unk2 = bf.ReadUint8()
m.Unk3 = bf.ReadUint8()
m.Data = bf.ReadBytes(uint(bf.ReadUint16())) m.Data = bf.ReadBytes(uint(bf.ReadUint16()))
return nil return nil
} }

View File

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

View File

@@ -18,8 +18,7 @@ type MsgMhfPresentBox struct {
Unk4 uint32 Unk4 uint32
Unk5 uint32 Unk5 uint32
Unk6 uint32 Unk6 uint32
Unk7 uint32 Unk7 []uint32
Unk8 uint32
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -37,8 +36,9 @@ func (m *MsgMhfPresentBox) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientC
m.Unk4 = bf.ReadUint32() m.Unk4 = bf.ReadUint32()
m.Unk5 = bf.ReadUint32() m.Unk5 = bf.ReadUint32()
m.Unk6 = bf.ReadUint32() m.Unk6 = bf.ReadUint32()
m.Unk7 = bf.ReadUint32() for i := uint32(0); i < m.Unk2; i++ {
m.Unk8 = bf.ReadUint32() m.Unk7 = append(m.Unk7, bf.ReadUint32())
}
return nil return nil
} }

View File

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

View File

@@ -1,15 +1,20 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfReadBeatLevelMyRanking represents the MSG_MHF_READ_BEAT_LEVEL_MY_RANKING // MsgMhfReadBeatLevelMyRanking represents the MSG_MHF_READ_BEAT_LEVEL_MY_RANKING
type MsgMhfReadBeatLevelMyRanking struct{} type MsgMhfReadBeatLevelMyRanking struct {
AckHandle uint32
Unk0 uint32
Unk1 uint32
Unk2 []int32
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfReadBeatLevelMyRanking) Opcode() network.PacketID { func (m *MsgMhfReadBeatLevelMyRanking) Opcode() network.PacketID {
@@ -18,7 +23,13 @@ func (m *MsgMhfReadBeatLevelMyRanking) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfReadBeatLevelMyRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfReadBeatLevelMyRanking) 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()
for i := 0; i < 16; i++ {
m.Unk2 = append(m.Unk2, bf.ReadInt32())
}
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -2,6 +2,7 @@ package mhfpacket
import ( import (
"errors" "errors"
_config "erupe-ce/config"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network" "erupe-ce/network"
@@ -34,12 +35,14 @@ 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()
m.Reward1 = uint16(bf.ReadUint32()) if _config.ErupeConfig.ClientMode != _config.Z1 {
m.Reward2 = uint16(bf.ReadUint32()) m.Reward1 = uint16(bf.ReadUint32())
m.Item1 = uint16(bf.ReadUint32()) m.Reward2 = uint16(bf.ReadUint32())
m.Item2 = uint16(bf.ReadUint32()) m.Item1 = uint16(bf.ReadUint32())
m.Quantity1 = uint16(bf.ReadUint32()) m.Item2 = uint16(bf.ReadUint32())
m.Quantity2 = uint16(bf.ReadUint32()) m.Quantity1 = uint16(bf.ReadUint32())
m.Quantity2 = uint16(bf.ReadUint32())
}
return nil return nil
} }

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

@@ -0,0 +1,29 @@
BEGIN;
CREATE TABLE IF NOT EXISTS tower (
char_id INT,
tr INT,
trp INT,
tsp INT,
block1 INT,
block2 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',
gems 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'
);
ALTER TABLE IF EXISTS guild_characters
ADD COLUMN IF NOT EXISTS tower_mission_1 INT;
ALTER TABLE IF EXISTS guild_characters
ADD COLUMN IF NOT EXISTS tower_mission_2 INT;
ALTER TABLE IF EXISTS guild_characters
ADD COLUMN IF NOT EXISTS tower_mission_3 INT;
ALTER TABLE IF EXISTS guilds
ADD COLUMN IF NOT EXISTS tower_mission_page INT DEFAULT 1;
ALTER TABLE IF EXISTS guilds
ADD COLUMN IF NOT EXISTS tower_rp INT DEFAULT 0;
END;

View File

@@ -27,15 +27,16 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) {
doAckBufSucceed(s, ackHandle, enumBf.Data()) doAckBufSucceed(s, ackHandle, enumBf.Data())
} }
// Temporary function to just return no results for many MSG_MHF_GET* packets. func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
func stubGetNoResults(s *Session, ackHandle uint32) { bf := byteframe.NewByteFrame()
resp := byteframe.NewByteFrame() bf.WriteUint32(uint32(s.server.erupeConfig.DevModeOptions.EarthIDOverride))
resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. (World ID?) bf.WriteUint32(0)
resp.WriteUint32(0) // Unk bf.WriteUint32(0)
resp.WriteUint32(0) // Unk bf.WriteUint32(uint32(len(data)))
resp.WriteUint32(0) // Entry count for i := range data {
bf.WriteBytes(data[i].Data())
doAckBufSucceed(s, ackHandle, resp.Data()) }
doAckBufSucceed(s, ackHandle, bf.Data())
} }
func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) { func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
@@ -1574,46 +1575,16 @@ func handleMsgMhfStampcardPrize(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfReadBeatLevel)
// This response is fixed and will never change on JP,
// but I've left it dynamic for possible other client differences.
resp := byteframe.NewByteFrame()
for i := 0; i < int(pkt.ValidIDCount); i++ {
resp.WriteUint32(pkt.IDs[i])
resp.WriteUint32(1)
resp.WriteUint32(1)
resp.WriteUint32(1)
}
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel)
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
}
func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfReadBeatLevelMyRanking(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetEarthStatus) pkt := p.(*mhfpacket.MsgMhfGetEarthStatus)
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start bf.WriteUint32(uint32(TimeWeekStart().Add(time.Hour * -24).Unix())) // Start
bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End bf.WriteUint32(uint32(TimeWeekNext().Add(time.Hour * 24).Unix())) // End
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride)
bf.WriteInt32(21) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)
bf.WriteInt32(0) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthMonsterOverride)
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
bf.WriteInt32(0) bf.WriteInt32(0)
@@ -1624,86 +1595,183 @@ func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetEarthValue) pkt := p.(*mhfpacket.MsgMhfGetEarthValue)
var earthValues []struct{ Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 } type EarthValues struct {
if pkt.ReqType == 3 { Value []uint32
earthValues = []struct { }
Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32
}{ var earthValues []EarthValues
// TW identical to JP switch pkt.ReqType {
{ case 1:
Unk0: 0x03E9, earthValues = []EarthValues{
Unk1: 0x24, {[]uint32{1, 312, 0, 0, 0, 0}},
}, {[]uint32{2, 99, 0, 0, 0, 0}},
{
Unk0: 0x2329,
Unk1: 0x03,
},
{
Unk0: 0x232A,
Unk1: 0x0A,
Unk2: 0x012C,
},
} }
} else if pkt.ReqType == 2 { case 2:
earthValues = []struct { earthValues = []EarthValues{
Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 {[]uint32{1, 5771, 0, 0, 0, 0}},
}{ {[]uint32{2, 1847, 0, 0, 0, 0}},
// JP response was empty
{
Unk0: 0x01,
Unk1: 0x168B,
},
{
Unk0: 0x02,
Unk1: 0x0737,
},
} }
} else if pkt.ReqType == 1 { case 3:
earthValues = []struct { earthValues = []EarthValues{
Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 {[]uint32{1001, 36, 0, 0, 0, 0}},
}{ {[]uint32{9001, 3, 0, 0, 0, 0}},
// JP simply sent 01 and 02 respectively {[]uint32{9002, 10, 300, 0, 0, 0}},
{
Unk0: 0x01,
Unk1: 0x0138,
},
{
Unk0: 0x02,
Unk1: 0x63,
},
} }
} }
resp := byteframe.NewByteFrame() var data []*byteframe.ByteFrame
resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. for _, i := range earthValues {
resp.WriteUint32(0) // Unk bf := byteframe.NewByteFrame()
resp.WriteUint32(0) // Unk for _, j := range i.Value {
resp.WriteUint32(uint32(len(earthValues))) // value count bf.WriteUint32(j)
for _, v := range earthValues { }
resp.WriteUint32(v.Unk0) data = append(data, bf)
resp.WriteUint32(v.Unk1)
resp.WriteUint32(v.Unk2)
resp.WriteUint32(v.Unk3)
resp.WriteUint32(v.Unk4)
resp.WriteUint32(v.Unk5)
} }
doAckEarthSucceed(s, pkt.AckHandle, data)
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
} }
func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {}
type SeibattleTimetable struct {
Start time.Time
End time.Time
}
type SeibattleKeyScore struct {
Unk0 uint8
Unk1 int32
}
type SeibattleCareer struct {
Unk0 uint16
Unk1 uint16
Unk2 uint16
}
type SeibattleOpponent struct {
Unk0 int32
Unk1 int8
}
type SeibattleConventionResult struct {
Unk0 uint32
Unk1 uint16
Unk2 uint16
Unk3 uint16
Unk4 uint16
}
type SeibattleCharScore struct {
Unk0 uint32
}
type SeibattleCurResult struct {
Unk0 uint32
Unk1 uint16
Unk2 uint16
Unk3 uint16
}
type Seibattle struct {
Timetable []SeibattleTimetable
KeyScore []SeibattleKeyScore
Career []SeibattleCareer
Opponent []SeibattleOpponent
ConventionResult []SeibattleConventionResult
CharScore []SeibattleCharScore
CurResult []SeibattleCurResult
}
func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetSeibattle) pkt := p.(*mhfpacket.MsgMhfGetSeibattle)
stubGetNoResults(s, pkt.AckHandle) var data []*byteframe.ByteFrame
seibattle := Seibattle{
Timetable: []SeibattleTimetable{
{TimeMidnight(), TimeMidnight().Add(time.Hour * 8)},
{TimeMidnight().Add(time.Hour * 8), TimeMidnight().Add(time.Hour * 16)},
{TimeMidnight().Add(time.Hour * 16), TimeMidnight().Add(time.Hour * 24)},
},
KeyScore: []SeibattleKeyScore{
{0, 0},
},
Career: []SeibattleCareer{
{0, 0, 0},
},
Opponent: []SeibattleOpponent{
{1, 1},
},
ConventionResult: []SeibattleConventionResult{
{0, 0, 0, 0, 0},
},
CharScore: []SeibattleCharScore{
{0},
},
CurResult: []SeibattleCurResult{
{0, 0, 0, 0},
},
}
switch pkt.Type {
case 1:
for _, timetable := range seibattle.Timetable {
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(timetable.Start.Unix()))
bf.WriteUint32(uint32(timetable.End.Unix()))
data = append(data, bf)
}
case 3: // Key score?
for _, keyScore := range seibattle.KeyScore {
bf := byteframe.NewByteFrame()
bf.WriteUint8(keyScore.Unk0)
bf.WriteInt32(keyScore.Unk1)
data = append(data, bf)
}
case 4: // Career?
for _, career := range seibattle.Career {
bf := byteframe.NewByteFrame()
bf.WriteUint16(career.Unk0)
bf.WriteUint16(career.Unk1)
bf.WriteUint16(career.Unk2)
data = append(data, bf)
}
case 5: // Opponent?
for _, opponent := range seibattle.Opponent {
bf := byteframe.NewByteFrame()
bf.WriteInt32(opponent.Unk0)
bf.WriteInt8(opponent.Unk1)
data = append(data, bf)
}
case 6: // Convention result?
for _, conventionResult := range seibattle.ConventionResult {
bf := byteframe.NewByteFrame()
bf.WriteUint32(conventionResult.Unk0)
bf.WriteUint16(conventionResult.Unk1)
bf.WriteUint16(conventionResult.Unk2)
bf.WriteUint16(conventionResult.Unk3)
bf.WriteUint16(conventionResult.Unk4)
data = append(data, bf)
}
case 7: // Char score?
for _, charScore := range seibattle.CharScore {
bf := byteframe.NewByteFrame()
bf.WriteUint32(charScore.Unk0)
data = append(data, bf)
}
case 8: // Cur result?
for _, curResult := range seibattle.CurResult {
bf := byteframe.NewByteFrame()
bf.WriteUint32(curResult.Unk0)
bf.WriteUint16(curResult.Unk1)
bf.WriteUint16(curResult.Unk2)
bf.WriteUint16(curResult.Unk3)
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -1,21 +1,73 @@
package channelserver package channelserver
import ( import (
"encoding/hex" "erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"time"
) )
type RyoudamaReward struct {
Unk0 uint8
Unk1 uint8
Unk2 uint16
Unk3 uint16
Unk4 uint16
Unk5 uint16
}
type RyoudamaKeyScore struct {
Unk0 uint8
Unk1 int32
}
type RyoudamaCharInfo struct {
CID uint32
Unk0 int32
Name string
}
type RyoudamaBoostInfo struct {
Start time.Time
End time.Time
}
type Ryoudama struct {
Reward []RyoudamaReward
KeyScore []RyoudamaKeyScore
CharInfo []RyoudamaCharInfo
BoostInfo []RyoudamaBoostInfo
Score []int32
}
func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetRyoudama) pkt := p.(*mhfpacket.MsgMhfGetRyoudama)
// likely guild related var data []*byteframe.ByteFrame
// REQ: 00 04 13 53 8F 18 00 ryoudama := Ryoudama{Score: []int32{0}}
// RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 01 00 01 FE 4E switch pkt.Request2 {
// REQ: 00 06 13 53 8F 18 00 case 4:
// RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 for _, score := range ryoudama.Score {
// REQ: 00 05 13 53 8F 18 00 bf := byteframe.NewByteFrame()
// RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 0E 2A 15 9E CC 00 00 00 01 82 79 83 4E 83 8A 81 5B 83 69 00 00 00 00 1E 55 B0 2F 00 00 00 01 8D F7 00 00 00 00 00 00 00 00 00 00 00 00 2A 15 9E CC 00 00 00 02 82 79 83 4E 83 8A 81 5B 83 69 00 00 00 00 03 D5 30 56 00 00 00 02 95 BD 91 F2 97 42 00 00 00 00 00 00 00 00 3F 57 76 9F 00 00 00 03 93 56 92 6E 96 B3 97 70 00 00 00 00 00 00 38 D9 0E C4 00 00 00 03 87 64 83 78 83 42 00 00 00 00 00 00 00 00 23 F3 B9 77 00 00 00 04 82 B3 82 CC 82 DC 82 E9 81 99 00 00 00 00 3F 1B 17 9C 00 00 00 04 82 B1 82 A4 82 BD 00 00 00 00 00 00 00 00 00 B9 F9 C0 00 00 00 05 82 CD 82 E9 82 A9 00 00 00 00 00 00 00 00 23 9F 9A EA 00 00 00 05 83 70 83 62 83 4C 83 83 83 49 00 00 00 00 38 D9 0E C4 00 00 00 06 87 64 83 78 83 42 00 00 00 00 00 00 00 00 1E 55 B0 2F 00 00 00 06 8D F7 00 00 00 00 00 00 00 00 00 00 00 00 03 D5 30 56 00 00 00 07 95 BD 91 F2 97 42 00 00 00 00 00 00 00 00 02 D3 B8 77 00 00 00 07 6F 77 6C 32 35 32 35 00 00 00 00 00 00 00 bf.WriteInt32(score)
data, _ := hex.DecodeString("0A218EAD0000000000000000000000010000000000000000") data = append(data, bf)
doAckBufSucceed(s, pkt.AckHandle, data) }
case 5:
for _, info := range ryoudama.CharInfo {
bf := byteframe.NewByteFrame()
bf.WriteUint32(info.CID)
bf.WriteInt32(info.Unk0)
bf.WriteBytes(stringsupport.PaddedString(info.Name, 14, true))
data = append(data, bf)
}
case 6:
for _, info := range ryoudama.BoostInfo {
bf := byteframe.NewByteFrame()
bf.WriteUint32(uint32(info.Start.Unix()))
bf.WriteUint32(uint32(info.End.Unix()))
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {}
@@ -31,8 +83,41 @@ func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCaravanMyScore)
var data []*byteframe.ByteFrame
/*
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
*/
doAckEarthSucceed(s, pkt.AckHandle, data)
}
func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCaravanRanking)
var data []*byteframe.ByteFrame
/* RYOUDAN
bf.WriteInt32(1)
bf.WriteUint32(2)
bf.WriteBytes(stringsupport.PaddedString("Test", 26, true))
*/
func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {} /* PERSONAL
bf.WriteInt32(1)
bf.WriteBytes(stringsupport.PaddedString("Test", 14, true))
*/
doAckEarthSucceed(s, pkt.AckHandle, data)
}
func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCaravanMyRank)
var data []*byteframe.ByteFrame
/*
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
*/
doAckEarthSucceed(s, pkt.AckHandle, data)
}

View File

@@ -35,16 +35,16 @@ const (
BroadcastTypeWorld = 0x0a BroadcastTypeWorld = 0x0a
) )
var commands map[string]config.Command var commands map[string]_config.Command
func init() { func init() {
commands = make(map[string]config.Command) commands = make(map[string]_config.Command)
zapConfig := zap.NewDevelopmentConfig() zapConfig := zap.NewDevelopmentConfig()
zapConfig.DisableCaller = true zapConfig.DisableCaller = true
zapLogger, _ := zapConfig.Build() zapLogger, _ := zapConfig.Build()
defer zapLogger.Sync() defer zapLogger.Sync()
logger := zapLogger.Named("commands") logger := zapLogger.Named("commands")
cmds := config.ErupeConfig.Commands cmds := _config.ErupeConfig.Commands
for _, cmd := range cmds { for _, cmd := range cmds {
commands[cmd.Name] = cmd commands[cmd.Name] = cmd
if cmd.Enabled { if cmd.Enabled {
@@ -55,7 +55,7 @@ func init() {
} }
} }
func sendDisabledCommandMessage(s *Session, cmd config.Command) { func sendDisabledCommandMessage(s *Session, cmd _config.Command) {
sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandDisabled"], cmd.Name)) sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandDisabled"], cmd.Name))
} }
@@ -211,7 +211,7 @@ func parseChatCommand(s *Session, command string) {
for _, course := range mhfcourse.Courses() { for _, course := range mhfcourse.Courses() {
for _, alias := range course.Aliases() { for _, alias := range course.Aliases() {
if strings.ToLower(name) == strings.ToLower(alias) { if strings.ToLower(name) == strings.ToLower(alias) {
if slices.Contains(s.server.erupeConfig.Courses, config.Course{Name: course.Aliases()[0], Enabled: true}) { if slices.Contains(s.server.erupeConfig.Courses, _config.Course{Name: course.Aliases()[0], Enabled: true}) {
var delta, rightsInt uint32 var delta, rightsInt uint32
if mhfcourse.CourseExists(course.ID, s.courses) { if mhfcourse.CourseExists(course.ID, s.courses) {
ei := slices.IndexFunc(s.courses, func(c mhfcourse.Course) bool { ei := slices.IndexFunc(s.courses, func(c mhfcourse.Course) bool {

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"erupe-ce/common/bfutil" "erupe-ce/common/bfutil"
"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/nullcomp" "erupe-ce/server/channelserver/compression/nullcomp"
@@ -12,7 +13,8 @@ import (
) )
const ( const (
pointerGender = 0x51 // +1 pointerGender = 0x51 // +1
pointerRP = 0x22D16 // +2 pointerRP = 0x22D16 // +2
pointerHouseTier = 0x1FB6C // +5 pointerHouseTier = 0x1FB6C // +5
pointerHouseData = 0x1FE01 // +195 pointerHouseData = 0x1FE01 // +195
@@ -26,6 +28,19 @@ const (
pointerHRP = 0x1FDF6 // +2 pointerHRP = 0x1FDF6 // +2
pointerGRP = 0x1FDFC // +4 pointerGRP = 0x1FDFC // +4
pointerKQF = 0x23D20 // +8 pointerKQF = 0x23D20 // +8
pointerRPZ = 0x1A076
pointerHouseTierZ = 0x16ECC
pointerHouseDataZ = 0x17161
pointerBookshelfDataZ = 0x195F8
pointerGalleryDataZ = 0x19680
pointerToreDataZ = 0x17014
pointerGardenDataZ = 0x19FB8
pointerWeaponTypeZ = 0x16A75
pointerWeaponIDZ = 0x1696A
pointerHRPZ = 0x17156
pointerGRPZ = 0x1715C
pointerKQFZ = 0x1B080
) )
type CharacterSaveData struct { type CharacterSaveData struct {
@@ -81,10 +96,6 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
return nil, err return nil, err
} }
if len(saveData.decompSave) < pointerKQF {
return nil, err
}
saveData.updateStructWithSaveData() saveData.updateStructWithSaveData()
return saveData, nil return saveData, nil
@@ -137,8 +148,13 @@ 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)
copy(save.decompSave[pointerRP:pointerRP+2], rpBytes) if _config.ErupeConfig.ClientMode == _config.ZZ {
copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF) copy(save.decompSave[pointerRP:pointerRP+2], rpBytes)
copy(save.decompSave[pointerKQF:pointerKQF+8], save.KQF)
} else {
copy(save.decompSave[pointerRPZ:pointerRPZ+2], rpBytes)
copy(save.decompSave[pointerKQFZ:pointerKQFZ+8], save.KQF)
}
} }
// This will update the save struct with the values stored in the character save // This will update the save struct with the values stored in the character save
@@ -150,20 +166,37 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
save.Gender = false save.Gender = false
} }
if !save.IsNewCharacter { if !save.IsNewCharacter {
save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2]) if _config.ErupeConfig.ClientMode == _config.ZZ {
save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5] save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRP : pointerRP+2])
save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195] save.HouseTier = save.decompSave[pointerHouseTier : pointerHouseTier+5]
save.BookshelfData = save.decompSave[pointerBookshelfData : pointerBookshelfData+5576] save.HouseData = save.decompSave[pointerHouseData : pointerHouseData+195]
save.GalleryData = save.decompSave[pointerGalleryData : pointerGalleryData+1748] save.BookshelfData = save.decompSave[pointerBookshelfData : pointerBookshelfData+5576]
save.ToreData = save.decompSave[pointerToreData : pointerToreData+240] save.GalleryData = save.decompSave[pointerGalleryData : pointerGalleryData+1748]
save.GardenData = save.decompSave[pointerGardenData : pointerGardenData+68] save.ToreData = save.decompSave[pointerToreData : pointerToreData+240]
save.WeaponType = save.decompSave[pointerWeaponType] save.GardenData = save.decompSave[pointerGardenData : pointerGardenData+68]
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponID : pointerWeaponID+2]) save.WeaponType = save.decompSave[pointerWeaponType]
save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRP : pointerHRP+2]) save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponID : pointerWeaponID+2])
if save.HRP == uint16(999) { save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRP : pointerHRP+2])
save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4])) if save.HRP == uint16(999) {
save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRP : pointerGRP+4]))
}
save.KQF = save.decompSave[pointerKQF : pointerKQF+8]
} else {
save.RP = binary.LittleEndian.Uint16(save.decompSave[pointerRPZ : pointerRPZ+2])
save.HouseTier = save.decompSave[pointerHouseTierZ : pointerHouseTierZ+5]
save.HouseData = save.decompSave[pointerHouseDataZ : pointerHouseDataZ+195]
save.BookshelfData = save.decompSave[pointerBookshelfDataZ : pointerBookshelfDataZ+5576]
save.GalleryData = save.decompSave[pointerGalleryDataZ : pointerGalleryDataZ+1748]
save.ToreData = save.decompSave[pointerToreDataZ : pointerToreDataZ+240]
save.GardenData = save.decompSave[pointerGardenDataZ : pointerGardenDataZ+68]
save.WeaponType = save.decompSave[pointerWeaponTypeZ]
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[pointerWeaponIDZ : pointerWeaponIDZ+2])
save.HRP = binary.LittleEndian.Uint16(save.decompSave[pointerHRPZ : pointerHRPZ+2])
if save.HRP == uint16(999) {
save.GR = grpToGR(binary.LittleEndian.Uint32(save.decompSave[pointerGRPZ : pointerGRPZ+4]))
}
save.KQF = save.decompSave[pointerKQFZ : pointerKQFZ+8]
} }
save.KQF = save.decompSave[pointerKQF : pointerKQF+8]
} }
return return
} }

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,7 @@ package channelserver
import ( import (
"encoding/hex" "encoding/hex"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
_config "erupe-ce/config"
"time" "time"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
@@ -71,7 +72,11 @@ 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 {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36)) if s.server.erupeConfig.ClientMode == _config.Z1 {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32))
} else {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
}
return return
} }
timestamps = generateDivaTimestamps(s, uint32(s.server.erupeConfig.DevModeOptions.DivaEvent), true) timestamps = generateDivaTimestamps(s, uint32(s.server.erupeConfig.DevModeOptions.DivaEvent), true)
@@ -79,9 +84,11 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
timestamps = generateDivaTimestamps(s, start, false) timestamps = generateDivaTimestamps(s, start, false)
} }
bf.WriteUint32(id) if s.server.erupeConfig.ClientMode != _config.Z1 {
for _, timestamp := range timestamps { bf.WriteUint32(id)
bf.WriteUint32(timestamp) }
for i := range timestamps {
bf.WriteUint32(timestamps[i])
} }
bf.WriteUint16(0x19) // Unk 00011001 bf.WriteUint16(0x19) // Unk 00011001

View File

@@ -2,6 +2,7 @@ package channelserver
import ( import (
"erupe-ce/common/token" "erupe-ce/common/token"
_config "erupe-ce/config"
"math" "math"
"time" "time"
@@ -90,14 +91,18 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
} }
func generateFeatureWeapons(count int) activeFeature { func generateFeatureWeapons(count int) activeFeature {
if count > 14 { max := 14
count = 14 if _config.ErupeConfig.ClientMode != _config.ZZ {
max = 13
}
if count > max {
count = max
} }
nums := make([]int, 0) nums := make([]int, 0)
var result int var result int
for len(nums) < count { for len(nums) < count {
rng := token.RNG() rng := token.RNG()
num := rng.Intn(14) num := rng.Intn(max)
exist := false exist := false
for _, v := range nums { for _, v := range nums {
if v == num { if v == num {

View File

@@ -7,6 +7,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
_config "erupe-ce/config"
"fmt" "fmt"
"math" "math"
"sort" "sort"
@@ -1390,7 +1391,12 @@ 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)
bf.WriteUint16(member.WeaponID) if s.server.erupeConfig.ClientMode != _config.ZZ {
// Magnet Spike crash workaround
bf.WriteUint16(0)
} else {
bf.WriteUint16(member.WeaponID)
}
if member.WeaponType == 1 || member.WeaponType == 5 || member.WeaponType == 10 { // If weapon is ranged if member.WeaponType == 1 || member.WeaponType == 5 || member.WeaponType == 10 { // If weapon is ranged
bf.WriteUint8(7) bf.WriteUint8(7)
} else { } else {

View File

@@ -222,8 +222,8 @@ func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfContractMercenary) pkt := p.(*mhfpacket.MsgMhfContractMercenary)
switch pkt.Op { switch pkt.Op {
case 0: case 0: // Form loan
s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, s.charID) s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID)
case 1: // Cancel lend case 1: // Cancel lend
s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID) s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID)
case 2: // Cancel loan case 2: // Cancel loan

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,98 @@
package channelserver
import (
"erupe-ce/common/byteframe"
"erupe-ce/network/mhfpacket"
)
func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetBreakSeibatuLevelReward)
bf := byteframe.NewByteFrame()
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
type WeeklySeibatuRankingReward struct {
Unk0 int32
Unk1 int32
Unk2 uint32
Unk3 int32
Unk4 int32
Unk5 int32
}
func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward)
var data []*byteframe.ByteFrame
weeklySeibatuRankingRewards := []WeeklySeibatuRankingReward{
{0, 0, 0, 0, 0, 0},
}
for _, reward := range weeklySeibatuRankingRewards {
bf := byteframe.NewByteFrame()
bf.WriteInt32(reward.Unk0)
bf.WriteInt32(reward.Unk1)
bf.WriteUint32(reward.Unk2)
bf.WriteInt32(reward.Unk3)
bf.WriteInt32(reward.Unk4)
bf.WriteInt32(reward.Unk5)
data = append(data, bf)
}
doAckEarthSucceed(s, pkt.AckHandle, data)
}
func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetFixedSeibatuRankingTable)
bf := byteframe.NewByteFrame()
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteBytes(make([]byte, 32))
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfReadBeatLevel)
// This response is fixed and will never change on JP,
// but I've left it dynamic for possible other client differences.
resp := byteframe.NewByteFrame()
for i := 0; i < int(pkt.ValidIDCount); i++ {
resp.WriteUint32(pkt.IDs[i])
resp.WriteUint32(1)
resp.WriteUint32(1)
resp.WriteUint32(1)
}
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel)
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
}
func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfReadBeatLevelAllRanking)
bf := byteframe.NewByteFrame()
bf.WriteUint32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
for i := 0; i < 100; i++ {
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteBytes(make([]byte, 32))
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfReadBeatLevelMyRanking(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfReadBeatLevelMyRanking)
bf := byteframe.NewByteFrame()
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}

View File

@@ -1,102 +1,477 @@
package channelserver package channelserver
import ( import (
"encoding/hex" "fmt"
"go.uber.org/zap"
"time"
"erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket" "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 {
Floors int32
Unk1 int32
Unk2 int32
Unk3 int32
}
func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) pkt := p.(*mhfpacket.MsgMhfGetTowerInfo)
var data []byte var data []*byteframe.ByteFrame
var err error type TowerInfo struct {
/* TRP []TowerInfoTRP
type: Skill []TowerInfoSkill
1 == TOWER_RANK_POINT, History []TowerInfoHistory
2 == GET_OWN_TOWER_SKILL Level []TowerInfoLevel
3 == GET_OWN_TOWER_LEVEL_V3
4 == TOWER_TOUHA_HISTORY
5 = ?
[] = type
req
resp
01 1d 01 fc 00 09 [00 00 00 01] 00 00 00 02 00 00 00 00
00 12 01 fc 00 09 01 00 00 18 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00
01 1d 01 fc 00 0a [00 00 00 02] 00 00 00 00 00 00 00 00
00 12 01 fc 00 0a 01 00 00 94 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 1d 01 ff 00 0f [00 00 00 04] 00 00 00 00 00 00 00 00
00 12 01 ff 00 0f 01 00 00 24 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 1d 01 fc 00 0b [00 00 00 05] 00 00 00 00 00 00 00 00
00 12 01 fc 00 0b 01 00 00 10 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 00
*/
switch pkt.InfoType {
case mhfpacket.TowerInfoTypeTowerRankPoint:
data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000")
case mhfpacket.TowerInfoTypeGetOwnTowerSkill:
//data, err = hex.DecodeString("0A218EAD000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
data, err = hex.DecodeString("0A218EAD0000000000000000000000010000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
case mhfpacket.TowerInfoTypeGetOwnTowerLevelV3:
panic("No known response values for GetOwnTowerLevelV3")
case mhfpacket.TowerInfoTypeTowerTouhaHistory:
data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000000000000000000000000000")
case mhfpacket.TowerInfoTypeUnk5:
data, err = hex.DecodeString("0A218EAD000000000000000000000000")
} }
towerInfo := TowerInfo{
TRP: []TowerInfoTRP{{0, 0}},
Skill: []TowerInfoSkill{{0, make([]int16, 40)}},
History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}},
Level: []TowerInfoLevel{{0, 0, 0, 0}, {0, 0, 0, 0}},
}
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(block1, 0), COALESCE(block2, 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].Floors, &towerInfo.Level[1].Floors, &tempSkills)
if err != nil { if err != nil {
stubGetNoResults(s, pkt.AckHandle) s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID)
} }
doAckBufSucceed(s, pkt.AckHandle, data)
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.WriteInt32(trp.TR)
bf.WriteInt32(trp.TRP)
data = append(data, bf)
}
case 2:
for _, skills := range towerInfo.Skill {
bf := byteframe.NewByteFrame()
bf.WriteInt32(skills.TSP)
for i := range skills.Unk1 {
bf.WriteInt16(skills.Unk1[i])
}
data = append(data, bf)
}
case 4:
for _, history := range towerInfo.History {
bf := byteframe.NewByteFrame()
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.Floors)
bf.WriteInt32(level.Unk1)
bf.WriteInt32(level.Unk2)
bf.WriteInt32(level.Unk3)
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostTowerInfo) pkt := p.(*mhfpacket.MsgMhfPostTowerInfo)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
if s.server.erupeConfig.DevModeOptions.QuestDebugTools {
s.logger.Debug(
p.Opcode().String(),
zap.Uint32("InfoType", pkt.InfoType),
zap.Uint32("Unk1", pkt.Unk1),
zap.Int32("Skill", pkt.Skill),
zap.Int32("TR", pkt.TR),
zap.Int32("TRP", pkt.TRP),
zap.Int32("Cost", pkt.Cost),
zap.Int32("Unk6", pkt.Unk6),
zap.Int32("Unk7", pkt.Unk7),
zap.Int32("Block1", pkt.Block1),
zap.Int64("Unk9", pkt.Unk9),
)
}
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.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.charID)
case 7:
s.server.db.Exec(`UPDATE tower SET tr=$1, trp=trp+$2, block1=block1+$3 WHERE char_id=$4`, pkt.TR, pkt.TRP, pkt.Block1, s.charID)
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
// Default missions
var tenrouiraiData = []TenrouiraiData{
{1, 1, 80, 0, 2, 2, 1, 1, 2, 2},
{1, 4, 16, 0, 2, 2, 1, 1, 2, 2},
{1, 6, 50, 0, 2, 2, 1, 0, 2, 2},
{1, 4, 12, 50, 2, 2, 1, 1, 2, 2},
{1, 3, 50, 0, 2, 2, 1, 1, 2, 2},
{2, 5, 40000, 0, 2, 2, 1, 0, 2, 2},
{1, 5, 50000, 50, 2, 2, 1, 1, 2, 2},
{2, 1, 60, 0, 2, 2, 1, 1, 2, 2},
{2, 3, 50, 0, 2, 1, 1, 0, 1, 2},
{2, 3, 40, 50, 2, 1, 1, 1, 1, 2},
{2, 4, 12, 0, 2, 1, 1, 1, 1, 2},
{2, 6, 40, 0, 2, 1, 1, 0, 1, 2},
{1, 1, 60, 50, 2, 1, 2, 1, 1, 2},
{1, 5, 50000, 0, 3, 1, 2, 1, 1, 2},
{1, 6, 50, 0, 3, 1, 2, 0, 1, 2},
{1, 4, 16, 50, 3, 1, 2, 1, 1, 2},
{1, 5, 50000, 0, 3, 1, 2, 1, 1, 2},
{2, 3, 40, 0, 3, 1, 2, 0, 1, 2},
{1, 3, 50, 50, 3, 1, 2, 1, 1, 2},
{2, 5, 40000, 0, 3, 1, 2, 1, 1, 1},
{2, 6, 40, 0, 3, 1, 2, 0, 1, 1},
{2, 1, 60, 50, 3, 1, 2, 1, 1, 1},
{2, 6, 50, 0, 3, 1, 2, 1, 1, 1},
{2, 4, 12, 0, 3, 1, 2, 0, 1, 1},
{1, 1, 80, 50, 3, 1, 2, 1, 1, 1},
{1, 5, 40000, 0, 3, 1, 2, 1, 1, 1},
{1, 3, 50, 0, 3, 1, 2, 0, 1, 1},
{1, 4, 16, 50, 3, 1, 0, 1, 1, 1},
{1, 6, 50, 0, 3, 1, 0, 1, 1, 1},
{2, 3, 40, 0, 3, 1, 0, 1, 1, 1},
{1, 1, 80, 50, 3, 1, 0, 0, 1, 1},
{2, 5, 40000, 0, 3, 1, 0, 0, 1, 1},
{2, 6, 40, 0, 3, 1, 0, 0, 1, 1},
}
type TenrouiraiProgress struct {
Page uint8
Mission1 uint16
Mission2 uint16
Mission3 uint16
}
type TenrouiraiReward struct {
Index uint8
Item []uint16 // 5
Quantity []uint8 // 5
}
type TenrouiraiKeyScore struct {
Unk0 uint8
Unk1 int32
}
type TenrouiraiData struct {
Block uint8
Mission uint8
// 1 = Floors climbed
// 2 = Collect antiques
// 3 = Open chests
// 4 = Cats saved
// 5 = TRP acquisition
// 6 = Monster slays
Goal uint16
Cost uint16
Skill1 uint8 // 80
Skill2 uint8 // 40
Skill3 uint8 // 40
Skill4 uint8 // 20
Skill5 uint8 // 40
Skill6 uint8 // 50
}
type TenrouiraiCharScore struct {
Score int32
Name string
}
type TenrouiraiTicket struct {
Unk0 uint8
RP uint32
Unk2 uint32
}
type Tenrouirai struct {
Progress []TenrouiraiProgress
Reward []TenrouiraiReward
KeyScore []TenrouiraiKeyScore
Data []TenrouiraiData
CharScore []TenrouiraiCharScore
Ticket []TenrouiraiTicket
} }
func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { 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) pkt := p.(*mhfpacket.MsgMhfGetTenrouirai)
var data []byte var data []*byteframe.ByteFrame
var err error
if pkt.Unk0 == 1 { tenrouirai := Tenrouirai{
data, err = hex.DecodeString("0A218EAD000000000000000000000001010000000000060010") Progress: []TenrouiraiProgress{{1, 0, 0, 0}},
} else if pkt.Unk2 == 4 { Data: tenrouiraiData,
data, err = hex.DecodeString("0A218EAD0000000000000000000000210101005000000202010102020104001000000202010102020106003200000202010002020104000C003202020101020201030032000002020101020202059C4000000202010002020105C35000320202010102020201003C00000202010102020203003200000201010001020203002800320201010101020204000C00000201010101020206002800000201010001020101003C00320201020101020105C35000000301020101020106003200000301020001020104001000320301020101020105C350000003010201010202030028000003010200010201030032003203010201010202059C4000000301020101010206002800000301020001010201003C00320301020101010206003200000301020101010204000C000003010200010101010050003203010201010101059C40000003010201010101030032000003010200010101040010003203010001010101060032000003010001010102030028000003010001010101010050003203010000010102059C4000000301000001010206002800000301000001010010") Ticket: []TenrouiraiTicket{{0, 0, 0}},
} else {
data = []byte{0x00, 0x00, 0x00, 0x00}
s.logger.Info("GET_TENROUIRAI request for unknown type")
} }
if err != nil {
panic(err) switch pkt.Unk1 {
case 1:
for _, tdata := range tenrouirai.Data {
bf := byteframe.NewByteFrame()
bf.WriteUint8(tdata.Block)
bf.WriteUint8(tdata.Mission)
bf.WriteUint16(tdata.Goal)
bf.WriteUint16(tdata.Cost)
bf.WriteUint8(tdata.Skill1)
bf.WriteUint8(tdata.Skill2)
bf.WriteUint8(tdata.Skill3)
bf.WriteUint8(tdata.Skill4)
bf.WriteUint8(tdata.Skill5)
bf.WriteUint8(tdata.Skill6)
data = append(data, bf)
}
case 2:
for _, reward := range tenrouirai.Reward {
bf := byteframe.NewByteFrame()
bf.WriteUint8(reward.Index)
bf.WriteUint16(reward.Item[0])
bf.WriteUint16(reward.Item[1])
bf.WriteUint16(reward.Item[2])
bf.WriteUint16(reward.Item[3])
bf.WriteUint16(reward.Item[4])
bf.WriteUint8(reward.Quantity[0])
bf.WriteUint8(reward.Quantity[1])
bf.WriteUint8(reward.Quantity[2])
bf.WriteUint8(reward.Quantity[3])
bf.WriteUint8(reward.Quantity[4])
data = append(data, bf)
}
case 4:
s.server.db.QueryRow(`SELECT tower_mission_page FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Page)
s.server.db.QueryRow(`SELECT SUM(tower_mission_1) AS _, SUM(tower_mission_2) AS _, SUM(tower_mission_3) AS _ FROM guild_characters WHERE guild_id=$1
`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Mission1, &tenrouirai.Progress[0].Mission2, &tenrouirai.Progress[0].Mission3)
if tenrouirai.Progress[0].Mission1 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-3].Goal {
tenrouirai.Progress[0].Mission1 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-3].Goal
}
if tenrouirai.Progress[0].Mission2 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-2].Goal {
tenrouirai.Progress[0].Mission2 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-2].Goal
}
if tenrouirai.Progress[0].Mission3 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal {
tenrouirai.Progress[0].Mission3 = tenrouiraiData[(tenrouirai.Progress[0].Page*3)-1].Goal
}
for _, progress := range tenrouirai.Progress {
bf := byteframe.NewByteFrame()
bf.WriteUint8(progress.Page)
bf.WriteUint16(progress.Mission1)
bf.WriteUint16(progress.Mission2)
bf.WriteUint16(progress.Mission3)
data = append(data, bf)
}
case 5:
if pkt.Unk3 > 3 {
pkt.Unk3 %= 3
if pkt.Unk3 == 0 {
pkt.Unk3 = 3
}
}
rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID)
for rows.Next() {
temp := TenrouiraiCharScore{}
rows.Scan(&temp.Name, &temp.Score)
tenrouirai.CharScore = append(tenrouirai.CharScore, temp)
}
for _, charScore := range tenrouirai.CharScore {
bf := byteframe.NewByteFrame()
bf.WriteInt32(charScore.Score)
bf.WriteBytes(stringsupport.PaddedString(charScore.Name, 14, true))
data = append(data, bf)
}
case 6:
s.server.db.QueryRow(`SELECT tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Ticket[0].RP)
for _, ticket := range tenrouirai.Ticket {
bf := byteframe.NewByteFrame()
bf.WriteUint8(ticket.Unk0)
bf.WriteUint32(ticket.RP)
bf.WriteUint32(ticket.Unk2)
data = append(data, bf)
}
} }
doAckBufSucceed(s, pkt.AckHandle, data)
doAckEarthSucceed(s, pkt.AckHandle, data)
} }
func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostTenrouirai) pkt := p.(*mhfpacket.MsgMhfPostTenrouirai)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
}
func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {} if s.server.erupeConfig.DevModeOptions.QuestDebugTools {
s.logger.Debug(
p.Opcode().String(),
zap.Uint8("Unk0", pkt.Unk0),
zap.Uint8("Op", pkt.Op),
zap.Uint32("GuildID", pkt.GuildID),
zap.Uint8("Unk1", pkt.Unk1),
zap.Uint16("Floors", pkt.Floors),
zap.Uint16("Antiques", pkt.Antiques),
zap.Uint16("Chests", pkt.Chests),
zap.Uint16("Cats", pkt.Cats),
zap.Uint16("TRP", pkt.TRP),
zap.Uint16("Slays", pkt.Slays),
)
}
func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) { if pkt.Op == 2 {
pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward) var page, requirement, donated int
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) s.server.db.QueryRow(`SELECT tower_mission_page, tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&page, &donated)
for i := 0; i < (page*3)+1; i++ {
requirement += int(tenrouiraiData[i].Cost)
}
bf := byteframe.NewByteFrame()
sd, err := GetCharacterSaveData(s, s.charID)
if err == nil && sd != nil {
sd.RP -= pkt.DonatedRP
sd.Save(s)
if donated+int(pkt.DonatedRP) >= requirement {
s.server.db.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID)
s.server.db.Exec(`UPDATE guild_characters SET tower_mission_1=NULL, tower_mission_2=NULL, tower_mission_3=NULL WHERE guild_id=$1`, pkt.GuildID)
pkt.DonatedRP = uint16(requirement - donated)
}
bf.WriteUint32(uint32(pkt.DonatedRP))
s.server.db.Exec(`UPDATE guilds SET tower_rp=tower_rp+$1 WHERE id=$2`, pkt.DonatedRP, pkt.GuildID)
} else {
bf.WriteUint32(0)
}
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
} else {
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
} }
func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPresentBox) pkt := p.(*mhfpacket.MsgMhfPresentBox)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) var data []*byteframe.ByteFrame
/*
bf.WriteUint32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
bf.WriteInt32(0)
*/
doAckEarthSucceed(s, pkt.AckHandle, data)
}
type GemInfo struct {
Gem uint16
Quantity uint16
}
type GemHistory struct {
Gem uint16
Message uint16
Timestamp time.Time
Sender string
} }
func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetGemInfo) pkt := p.(*mhfpacket.MsgMhfGetGemInfo)
var data []*byteframe.ByteFrame
gemInfo := []GemInfo{}
gemHistory := []GemHistory{}
tempGems := "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 gems FROM tower WHERE char_id=$1`, s.charID).Scan(&tempGems)
for i, v := range stringsupport.CSVElems(tempGems) {
gemInfo = append(gemInfo, GemInfo{uint16(((i / 5) * 256) + ((i % 5) + 1)), uint16(v)})
}
switch pkt.Unk0 {
case 1:
for _, info := range gemInfo {
bf := byteframe.NewByteFrame()
bf.WriteUint16(info.Gem)
bf.WriteUint16(info.Quantity)
data = append(data, bf)
}
case 2:
for _, history := range gemHistory {
bf := byteframe.NewByteFrame()
bf.WriteUint16(history.Gem)
bf.WriteUint16(history.Message)
bf.WriteUint32(uint32(history.Timestamp.Unix()))
bf.WriteBytes(stringsupport.PaddedString(history.Sender, 14, true))
data = append(data, bf)
}
}
doAckEarthSucceed(s, pkt.AckHandle, data)
}
func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostGemInfo)
if s.server.erupeConfig.DevModeOptions.QuestDebugTools {
s.logger.Debug(
p.Opcode().String(),
zap.Uint32("Op", pkt.Op),
zap.Uint32("Unk1", pkt.Unk1),
zap.Int32("Gem", pkt.Gem),
zap.Int32("Quantity", pkt.Quantity),
zap.Int32("CID", pkt.CID),
zap.Int32("Message", pkt.Message),
zap.Int32("Unk6", pkt.Unk6),
)
}
gems := "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 gems FROM tower WHERE char_id=$1`, s.charID).Scan(&gems)
switch pkt.Op {
case 1: // Add gem
i := int(((pkt.Gem / 256) * 5) + (((pkt.Gem - ((pkt.Gem / 256) * 256)) - 1) % 5))
s.server.db.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.charID)
case 2: // Transfer gem
// no way im doing this for now
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetNotice)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostNotice)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}

View File

@@ -22,7 +22,7 @@ type Config struct {
Logger *zap.Logger Logger *zap.Logger
DB *sqlx.DB DB *sqlx.DB
DiscordBot *discordbot.DiscordBot DiscordBot *discordbot.DiscordBot
ErupeConfig *config.Config ErupeConfig *_config.Config
Name string Name string
Enable bool Enable bool
} }
@@ -43,7 +43,7 @@ type Server struct {
Port uint16 Port uint16
logger *zap.Logger logger *zap.Logger
db *sqlx.DB db *sqlx.DB
erupeConfig *config.Config erupeConfig *_config.Config
acceptConns chan net.Conn acceptConns chan net.Conn
deleteConns chan net.Conn deleteConns chan net.Conn
sessions map[net.Conn]*Session sessions map[net.Conn]*Session

View File

@@ -9,14 +9,14 @@ import (
type DiscordBot struct { type DiscordBot struct {
Session *discordgo.Session Session *discordgo.Session
config *config.Config config *_config.Config
logger *zap.Logger logger *zap.Logger
MainGuild *discordgo.Guild MainGuild *discordgo.Guild
RealtimeChannel *discordgo.Channel RealtimeChannel *discordgo.Channel
} }
type Options struct { type Options struct {
Config *config.Config Config *_config.Config
Logger *zap.Logger Logger *zap.Logger
} }

View File

@@ -18,7 +18,7 @@ import (
type Server struct { type Server struct {
sync.Mutex sync.Mutex
logger *zap.Logger logger *zap.Logger
erupeConfig *config.Config erupeConfig *_config.Config
db *sqlx.DB db *sqlx.DB
listener net.Listener listener net.Listener
isShuttingDown bool isShuttingDown bool
@@ -28,7 +28,7 @@ type Server struct {
type Config struct { type Config struct {
Logger *zap.Logger Logger *zap.Logger
DB *sqlx.DB DB *sqlx.DB
ErupeConfig *config.Config ErupeConfig *_config.Config
} }
// NewServer creates a new Server type. // NewServer creates a new Server type.
@@ -68,7 +68,7 @@ func (s *Server) Shutdown() {
s.listener.Close() s.listener.Close()
} }
//acceptClients handles accepting new clients in a loop. // acceptClients handles accepting new clients in a loop.
func (s *Server) acceptClients() { func (s *Server) acceptClients() {
for { for {
conn, err := s.listener.Accept() conn, err := s.listener.Accept()

View File

@@ -3,13 +3,13 @@ package entranceserver
import ( import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
_config "erupe-ce/config"
"fmt" "fmt"
"net" "net"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/config"
"erupe-ce/server/channelserver" "erupe-ce/server/channelserver"
) )
@@ -19,11 +19,17 @@ var season uint8
// Server Channels // Server Channels
var currentplayers uint16 var currentplayers uint16
func encodeServerInfo(config *config.Config, s *Server, local bool) []byte { func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
serverInfos := config.Entrance.Entries serverInfos := config.Entrance.Entries
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
for serverIdx, si := range serverInfos { for serverIdx, si := range serverInfos {
// Prevent MezFes Worlds displaying on Z1
if config.ClientMode == _config.Z1 {
if si.Type == 6 {
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 {
@@ -91,8 +97,17 @@ func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byt
return bf.Data() return bf.Data()
} }
func makeSv2Resp(config *config.Config, s *Server, local bool) []byte { 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
var mf int
if config.ClientMode == _config.Z1 {
for _, si := range serverInfos {
if si.Type == 6 {
mf++
}
}
}
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 {
@@ -100,7 +115,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)), 0x00)) bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(serverInfos)-mf), 0x00))
return bf.Data() return bf.Data()
} }

View File

@@ -16,14 +16,14 @@ import (
type Config struct { type Config struct {
Logger *zap.Logger Logger *zap.Logger
DB *sqlx.DB DB *sqlx.DB
ErupeConfig *config.Config ErupeConfig *_config.Config
} }
// Server is a MHF sign server. // Server is a MHF sign server.
type Server struct { type Server struct {
sync.Mutex sync.Mutex
logger *zap.Logger logger *zap.Logger
erupeConfig *config.Config erupeConfig *_config.Config
sessions map[int]*Session sessions map[int]*Session
db *sqlx.DB db *sqlx.DB
listener net.Listener listener net.Listener

View File

@@ -18,14 +18,14 @@ import (
type Config struct { type Config struct {
Logger *zap.Logger Logger *zap.Logger
DB *sqlx.DB DB *sqlx.DB
ErupeConfig *config.Config ErupeConfig *_config.Config
} }
// Server is the MHF custom launcher sign server. // Server is the MHF custom launcher sign server.
type Server struct { type Server struct {
sync.Mutex sync.Mutex
logger *zap.Logger logger *zap.Logger
erupeConfig *config.Config erupeConfig *_config.Config
db *sqlx.DB db *sqlx.DB
httpServer *http.Server httpServer *http.Server
isShuttingDown bool isShuttingDown bool