From 5f975c97b56307f2519226bbac9537e98e446f27 Mon Sep 17 00:00:00 2001 From: stratic-dev Date: Sat, 12 Oct 2024 22:37:42 +0100 Subject: [PATCH] Config / DB now its own package --- config/config.go | 27 +- main.go | 180 ++---- network/crypt_conn.go | 4 +- .../mhfpacket/msg_mhf_acquire_cafe_item.go | 4 +- network/mhfpacket/msg_mhf_apply_dist_item.go | 6 +- .../mhfpacket/msg_mhf_enumerate_dist_item.go | 4 +- network/mhfpacket/msg_mhf_enumerate_quest.go | 4 +- network/mhfpacket/msg_mhf_enumerate_shop.go | 4 +- network/mhfpacket/msg_mhf_savedata.go | 4 +- network/mhfpacket/msg_mhf_stampcard_stamp.go | 6 +- .../mhfpacket/msg_mhf_update_myhouse_info.go | 8 +- .../msg_sys_create_acquire_semaphore.go | 4 +- network/mhfpacket/msg_sys_create_semaphore.go | 4 +- network/mhfpacket/msg_sys_terminal_log.go | 4 +- server/api/api_server.go | 21 +- server/api/dbutils.go | 67 +- server/api/endpoints.go | 15 +- server/channelserver/ack_helpers.go | 15 +- server/channelserver/handlers.go | 376 +++++++----- server/channelserver/handlers_achievement.go | 30 +- server/channelserver/handlers_bbs.go | 15 +- server/channelserver/handlers_cafe.go | 155 +++-- server/channelserver/handlers_campaign.go | 14 +- server/channelserver/handlers_caravan.go | 12 +- server/channelserver/handlers_cast_binary.go | 194 +++--- server/channelserver/handlers_character.go | 64 +- server/channelserver/handlers_clients.go | 43 +- server/channelserver/handlers_data.go | 109 ++-- server/channelserver/handlers_distitem.go | 70 ++- server/channelserver/handlers_diva.go | 65 +- server/channelserver/handlers_event.go | 52 +- server/channelserver/handlers_festa.go | 197 +++--- server/channelserver/handlers_guild.go | 581 ++++++++++-------- .../channelserver/handlers_guild_adventure.go | 80 ++- .../channelserver/handlers_guild_alliance.go | 94 +-- server/channelserver/handlers_guild_member.go | 28 +- server/channelserver/handlers_guild_scout.go | 149 +++-- .../channelserver/handlers_guild_tresure.go | 78 ++- server/channelserver/handlers_house.go | 196 ++++-- server/channelserver/handlers_kouryou.go | 36 +- server/channelserver/handlers_mail.go | 108 ++-- server/channelserver/handlers_mercenary.go | 175 ++++-- server/channelserver/handlers_object.go | 27 +- server/channelserver/handlers_plate.go | 117 ++-- server/channelserver/handlers_quest.go | 188 +++--- server/channelserver/handlers_register.go | 37 +- server/channelserver/handlers_rengoku.go | 69 ++- server/channelserver/handlers_reserve.go | 4 +- server/channelserver/handlers_reward.go | 8 +- server/channelserver/handlers_seibattle.go | 16 +- server/channelserver/handlers_semaphore.go | 64 +- server/channelserver/handlers_shop_gacha.go | 244 +++++--- server/channelserver/handlers_stage.go | 160 ++--- server/channelserver/handlers_tactics.go | 14 +- server/channelserver/handlers_tournament.go | 6 +- server/channelserver/handlers_tower.go | 105 ++-- server/channelserver/handlers_users.go | 43 +- server/channelserver/sys_broadcast.go | 8 +- server/channelserver/sys_channel_server.go | 60 +- server/channelserver/sys_discord.go | 21 +- ...andlers_table.go => sys_handlers_table.go} | 114 ++-- server/channelserver/sys_language.go | 8 +- server/channelserver/sys_ravi.go | 6 +- server/channelserver/sys_session.go | 62 +- server/discordbot/discord_bot.go | 18 +- .../entrance_server.go | 40 +- .../{entranceserver => entrance}/make_resp.go | 62 +- server/sign/dbutils.go | 318 ++++++++++ server/{signserver => sign}/dsgn_resp.go | 62 +- server/{signserver => sign}/respid.go | 2 +- server/{signserver => sign}/session.go | 37 +- server/{signserver => sign}/sign_server.go | 35 +- server/signserver/dbutils.go | 260 -------- utils/db/db.go | 77 +++ utils/mhfcourse/mhfcourse.go | 4 +- utils/mhfitem/mhfitem.go | 10 +- 76 files changed, 3249 insertions(+), 2359 deletions(-) rename server/channelserver/{handlers_table.go => sys_handlers_table.go} (89%) rename server/{entranceserver => entrance}/entrance_server.go (71%) rename server/{entranceserver => entrance}/make_resp.go (64%) create mode 100644 server/sign/dbutils.go rename server/{signserver => sign}/dsgn_resp.go (86%) rename server/{signserver => sign}/respid.go (98%) rename server/{signserver => sign}/session.go (78%) rename server/{signserver => sign}/sign_server.go (68%) delete mode 100644 server/signserver/dbutils.go create mode 100644 utils/db/db.go diff --git a/config/config.go b/config/config.go index c5a39f052..72fedda80 100644 --- a/config/config.go +++ b/config/config.go @@ -1,4 +1,4 @@ -package _config +package config import ( "fmt" @@ -6,6 +6,7 @@ import ( "net" "os" "strings" + "sync" "time" "github.com/spf13/viper" @@ -299,15 +300,10 @@ type EntranceChannelInfo struct { CurrentPlayers uint16 } -var ErupeConfig *Config - -func init() { - var err error - ErupeConfig, err = LoadConfig() - if err != nil { - preventClose(fmt.Sprintf("Failed to load config: %s", err.Error())) - } -} +var ( + once sync.Once + ErupeConfig *Config +) // getOutboundIP4 gets the preferred outbound ip4 of this machine // From https://stackoverflow.com/a/37382208 @@ -368,7 +364,16 @@ func LoadConfig() (*Config, error) { return c, nil } - +func GetConfig() *Config { + once.Do(func() { + var err error + ErupeConfig, err = LoadConfig() + if err != nil { + preventClose(fmt.Sprintf("Failed to load config: %s", err.Error())) + } + }) + return ErupeConfig +} func preventClose(text string) { if ErupeConfig.DisableSoftCrash { os.Exit(0) diff --git a/main.go b/main.go index b605dcf57..7da52a3e4 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ package main import ( - _config "erupe-ce/config" + "erupe-ce/config" "fmt" "net" "os" @@ -13,27 +13,19 @@ import ( "erupe-ce/server/api" "erupe-ce/server/channelserver" "erupe-ce/server/discordbot" - "erupe-ce/server/entranceserver" + "erupe-ce/server/entrance" + "erupe-ce/server/sign" + "erupe-ce/utils/db" "erupe-ce/utils/logger" - "erupe-ce/server/signserver" "erupe-ce/utils/gametime" - "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "go.uber.org/zap" ) var mainLogger logger.Logger -// Temporary DB auto clean on startup for quick development & testing. -func cleanDB(db *sqlx.DB) { - _ = db.MustExec("DELETE FROM guild_characters") - _ = db.MustExec("DELETE FROM guilds") - _ = db.MustExec("DELETE FROM characters") - _ = db.MustExec("DELETE FROM users") -} - var Commit = func() string { if info, ok := debug.ReadBuildInfo(); ok { for _, setting := range info.Settings { @@ -54,96 +46,24 @@ func initLogger() { mainLogger = logger.Get().Named("main") } + func main() { var err error - config := _config.ErupeConfig + config := config.GetConfig() initLogger() mainLogger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit())) mainLogger.Info(fmt.Sprintf("Client Mode: %s (%d)", config.ClientMode, config.ClientID)) - if config.Database.Password == "" { - preventClose("Database password is blank") - } + checkAndExitIf(config.Database.Password == "", "Database password is blank") - if net.ParseIP(config.Host) == nil { - ips, _ := net.LookupIP(config.Host) - for _, ip := range ips { - if ip != nil { - config.Host = ip.String() - break - } - } - if net.ParseIP(config.Host) == nil { - preventClose("Invalid host address") - } - } + resolveHostIP() - // Discord bot - var discordBot *discordbot.DiscordBot = nil + discordBot := initializeDiscordBot() - if config.Discord.Enabled { - bot, err := discordbot.NewDiscordBot(discordbot.Options{ - Config: _config.ErupeConfig, - }) - DiscordFailMsg := "Discord: Failed to start, %s" - if err != nil { - preventClose(fmt.Sprintf(DiscordFailMsg, err.Error())) - } - - // Discord bot - err = bot.Start() - - if err != nil { - preventClose(fmt.Sprintf(DiscordFailMsg, err.Error())) - } - - discordBot = bot - - _, err = discordBot.Session.ApplicationCommandBulkOverwrite(discordBot.Session.State.User.ID, "", discordbot.Commands) - if err != nil { - preventClose(fmt.Sprintf(DiscordFailMsg, err.Error())) - } - - mainLogger.Info("Discord: Started successfully") - } else { - mainLogger.Info("Discord: Disabled") - } - - // Create the postgres DB pool. - connectString := fmt.Sprintf( - "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", - config.Database.Host, - config.Database.Port, - config.Database.User, - config.Database.Password, - config.Database.Database, - ) - - db, err := sqlx.Open("postgres", connectString) + database, err := db.InitDB(config) if err != nil { - preventClose(fmt.Sprintf("Database: Failed to open, %s", err.Error())) - } - - // Test the DB connection. - err = db.Ping() - if err != nil { - preventClose(fmt.Sprintf("Database: Failed to ping, %s", err.Error())) - } - mainLogger.Info("Database: Started successfully") - - // Clear stale data - if config.DebugOptions.ProxyPort == 0 { - _ = db.MustExec("DELETE FROM sign_sessions") - } - _ = db.MustExec("DELETE FROM servers") - _ = db.MustExec(`UPDATE guild_characters SET treasure_hunt=NULL`) - - // Clean the DB if the option is on. - if config.DebugOptions.CleanDB { - mainLogger.Info("Database: Started clearing...") - cleanDB(db) - mainLogger.Info("Database: Finished clearing") + mainLogger.Fatal(fmt.Sprintf("Database initialization failed: %s", err)) } mainLogger.Info(fmt.Sprintf("Server Time: %s", gametime.TimeAdjusted().String())) @@ -151,16 +71,10 @@ func main() { // Now start our server(s). // Entrance server. - entranceLogger := logger.Get().Named("entrance") - var entranceServer *entranceserver.Server + var entranceServer *entrance.EntranceServer if config.Entrance.Enabled { - entranceServer = entranceserver.NewServer( - &entranceserver.Config{ - Logger: entranceLogger, - ErupeConfig: _config.ErupeConfig, - DB: db, - }) + entranceServer = entrance.NewServer() err = entranceServer.Start() if err != nil { preventClose(fmt.Sprintf("Entrance: Failed to start, %s", err.Error())) @@ -171,13 +85,9 @@ func main() { } // Sign server. - var signServer *signserver.Server + var signServer *sign.SignServer if config.Sign.Enabled { - signServer = signserver.NewServer( - &signserver.Config{ - ErupeConfig: _config.ErupeConfig, - DB: db, - }) + signServer = sign.NewServer() err = signServer.Start() if err != nil { preventClose(fmt.Sprintf("Sign: Failed to start, %s", err.Error())) @@ -188,14 +98,10 @@ func main() { } // Api server - var ApiServer *api.APIServer + var apiServer *api.APIServer if config.API.Enabled { - ApiServer = api.NewAPIServer( - &api.Config{ - ErupeConfig: _config.ErupeConfig, - DB: db, - }) - err = ApiServer.Start() + apiServer = api.NewAPIServer() + err = apiServer.Start() if err != nil { preventClose(fmt.Sprintf("API: Failed to start, %s", err.Error())) } @@ -203,8 +109,7 @@ func main() { } else { mainLogger.Info("API: Disabled") } - - var channelServers []*channelserver.Server + var channelServers []*channelserver.ChannelServer if config.Channel.Enabled { channelQuery := "" si := 0 @@ -214,10 +119,8 @@ func main() { for i, ce := range ee.Channels { sid := (4096 + si*256) + (16 + ci) c := *channelserver.NewServer(&channelserver.Config{ - ID: uint16(sid), - ErupeConfig: _config.ErupeConfig, - DB: db, - DiscordBot: discordBot, + ID: uint16(sid), + DiscordBot: discordBot, }) if ee.IP == "" { c.IP = config.Host @@ -242,7 +145,7 @@ func main() { } // Register all servers in DB - _ = db.MustExec(channelQuery) + _ = database.MustExec(channelQuery) for _, c := range channelServers { c.Channels = channelServers @@ -278,7 +181,7 @@ func main() { } if config.API.Enabled { - ApiServer.Shutdown() + apiServer.Shutdown() } if config.Entrance.Enabled { @@ -295,7 +198,7 @@ func wait() { } func preventClose(text string) { - if _config.ErupeConfig.DisableSoftCrash { + if config.GetConfig().DisableSoftCrash { os.Exit(0) } mainLogger.Error(fmt.Sprintf(("\nFailed to start Erupe:\n" + text))) @@ -303,3 +206,38 @@ func preventClose(text string) { mainLogger.Error(fmt.Sprintf(("\nPress Enter/Return to exit..."))) os.Exit(0) } + +func checkAndExitIf(condition bool, message string) { + if condition { + preventClose(message) + } +} + +func resolveHostIP() { + if net.ParseIP(config.GetConfig().Host) == nil { + ips, err := net.LookupIP(config.GetConfig().Host) + if err == nil && len(ips) > 0 { + config.GetConfig().Host = ips[0].String() + } + checkAndExitIf(net.ParseIP(config.GetConfig().Host) == nil, "Invalid host address") + } +} + +func initializeDiscordBot() *discordbot.DiscordBot { + if !config.GetConfig().Discord.Enabled { + mainLogger.Info("Discord: Disabled") + return nil + } + + bot, err := discordbot.NewDiscordBot() + checkAndExitIf(err != nil, fmt.Sprintf("Discord: Failed to start, %s", err)) + + err = bot.Start() + checkAndExitIf(err != nil, fmt.Sprintf("Discord: Failed to start, %s", err)) + + _, err = bot.Session.ApplicationCommandBulkOverwrite(bot.Session.State.User.ID, "", discordbot.Commands) + checkAndExitIf(err != nil, fmt.Sprintf("Discord: Failed to register commands, %s", err)) + + mainLogger.Info("Discord: Started successfully") + return bot +} diff --git a/network/crypt_conn.go b/network/crypt_conn.go index 5bc6ddf5c..b6fc2d12a 100644 --- a/network/crypt_conn.go +++ b/network/crypt_conn.go @@ -3,7 +3,7 @@ package network import ( "encoding/hex" "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/crypto" "fmt" "io" @@ -51,7 +51,7 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) { var encryptedPacketBody []byte // Don't know when support for this was added, works in Forward.4, doesn't work in Season 6.0 - if _config.ErupeConfig.ClientID < _config.F1 { + if config.GetConfig().ClientID < config.F1 { encryptedPacketBody = make([]byte, cph.DataSize) } else { encryptedPacketBody = make([]byte, uint32(cph.DataSize)+(uint32(cph.Pf0-0x03)*0x1000)) diff --git a/network/mhfpacket/msg_mhf_acquire_cafe_item.go b/network/mhfpacket/msg_mhf_acquire_cafe_item.go index c9b7e7bc4..8a4c273ec 100644 --- a/network/mhfpacket/msg_mhf_acquire_cafe_item.go +++ b/network/mhfpacket/msg_mhf_acquire_cafe_item.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -30,7 +30,7 @@ func (m *MsgMhfAcquireCafeItem) Parse(bf *byteframe.ByteFrame) error { m.ItemType = bf.ReadUint16() m.ItemID = bf.ReadUint16() m.Quant = bf.ReadUint16() - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { m.PointCost = bf.ReadUint32() } else { m.PointCost = uint32(bf.ReadUint16()) diff --git a/network/mhfpacket/msg_mhf_apply_dist_item.go b/network/mhfpacket/msg_mhf_apply_dist_item.go index 7ed1105db..0d33413ea 100644 --- a/network/mhfpacket/msg_mhf_apply_dist_item.go +++ b/network/mhfpacket/msg_mhf_apply_dist_item.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" ) @@ -26,10 +26,10 @@ func (m *MsgMhfApplyDistItem) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() m.DistributionType = bf.ReadUint8() m.DistributionID = bf.ReadUint32() - if _config.ErupeConfig.ClientID >= _config.G8 { + if config.GetConfig().ClientID >= config.G8 { m.Unk2 = bf.ReadUint32() } - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { m.Unk3 = bf.ReadUint32() } return nil diff --git a/network/mhfpacket/msg_mhf_enumerate_dist_item.go b/network/mhfpacket/msg_mhf_enumerate_dist_item.go index 72038d707..d90774102 100644 --- a/network/mhfpacket/msg_mhf_enumerate_dist_item.go +++ b/network/mhfpacket/msg_mhf_enumerate_dist_item.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" ) @@ -27,7 +27,7 @@ func (m *MsgMhfEnumerateDistItem) Parse(bf *byteframe.ByteFrame) error { m.DistType = bf.ReadUint8() m.Unk1 = bf.ReadUint8() m.Unk2 = bf.ReadUint16() // Maximum? Hardcoded to 256 - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { m.Unk3 = bf.ReadBytes(uint(bf.ReadUint8())) } return nil diff --git a/network/mhfpacket/msg_mhf_enumerate_quest.go b/network/mhfpacket/msg_mhf_enumerate_quest.go index d946cd301..c05d203c7 100644 --- a/network/mhfpacket/msg_mhf_enumerate_quest.go +++ b/network/mhfpacket/msg_mhf_enumerate_quest.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -29,7 +29,7 @@ func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame) error { m.Unk0 = bf.ReadUint8() m.World = bf.ReadUint8() m.Counter = bf.ReadUint16() - if _config.ErupeConfig.ClientID <= _config.Z1 { + if config.GetConfig().ClientID <= config.Z1 { m.Offset = uint16(bf.ReadUint8()) } else { m.Offset = bf.ReadUint16() diff --git a/network/mhfpacket/msg_mhf_enumerate_shop.go b/network/mhfpacket/msg_mhf_enumerate_shop.go index 6994c91f0..d69dae84b 100644 --- a/network/mhfpacket/msg_mhf_enumerate_shop.go +++ b/network/mhfpacket/msg_mhf_enumerate_shop.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -31,7 +31,7 @@ func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame) error { m.ShopID = bf.ReadUint32() m.Limit = bf.ReadUint16() m.Unk3 = bf.ReadUint8() - if _config.ErupeConfig.ClientID >= _config.G2 { + if config.GetConfig().ClientID >= config.G2 { m.Unk4 = bf.ReadUint8() m.Unk5 = bf.ReadUint32() } diff --git a/network/mhfpacket/msg_mhf_savedata.go b/network/mhfpacket/msg_mhf_savedata.go index 2dce6eca2..008d6061f 100644 --- a/network/mhfpacket/msg_mhf_savedata.go +++ b/network/mhfpacket/msg_mhf_savedata.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -29,7 +29,7 @@ func (m *MsgMhfSavedata) Parse(bf *byteframe.ByteFrame) error { m.AllocMemSize = bf.ReadUint32() m.SaveType = bf.ReadUint8() m.Unk1 = bf.ReadUint32() - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { m.DataSize = bf.ReadUint32() } if m.DataSize == 0 { // seems to be used when DataSize = 0 rather than on savetype? diff --git a/network/mhfpacket/msg_mhf_stampcard_stamp.go b/network/mhfpacket/msg_mhf_stampcard_stamp.go index 14604dbb1..e4980ef2f 100644 --- a/network/mhfpacket/msg_mhf_stampcard_stamp.go +++ b/network/mhfpacket/msg_mhf_stampcard_stamp.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -31,12 +31,12 @@ func (m *MsgMhfStampcardStamp) Opcode() network.PacketID { func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() m.HR = bf.ReadUint16() - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { m.GR = bf.ReadUint16() } m.Stamps = bf.ReadUint16() bf.ReadUint16() // Zeroed - if _config.ErupeConfig.ClientID >= _config.Z2 { + if config.GetConfig().ClientID >= config.Z2 { m.Reward1 = uint16(bf.ReadUint32()) m.Reward2 = uint16(bf.ReadUint32()) m.Item1 = uint16(bf.ReadUint32()) diff --git a/network/mhfpacket/msg_mhf_update_myhouse_info.go b/network/mhfpacket/msg_mhf_update_myhouse_info.go index ccbb4df59..2b75a2d9a 100644 --- a/network/mhfpacket/msg_mhf_update_myhouse_info.go +++ b/network/mhfpacket/msg_mhf_update_myhouse_info.go @@ -3,7 +3,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" ) @@ -22,11 +22,11 @@ func (m *MsgMhfUpdateMyhouseInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfUpdateMyhouseInfo) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { m.Data = bf.ReadBytes(362) - } else if _config.ErupeConfig.ClientID >= _config.GG { + } else if config.GetConfig().ClientID >= config.GG { m.Data = bf.ReadBytes(338) - } else if _config.ErupeConfig.ClientID >= _config.F5 { + } else if config.GetConfig().ClientID >= config.F5 { // G1 is a guess m.Data = bf.ReadBytes(314) } else { diff --git a/network/mhfpacket/msg_sys_create_acquire_semaphore.go b/network/mhfpacket/msg_sys_create_acquire_semaphore.go index a3f7cce3d..271e602d0 100644 --- a/network/mhfpacket/msg_sys_create_acquire_semaphore.go +++ b/network/mhfpacket/msg_sys_create_acquire_semaphore.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" ) @@ -24,7 +24,7 @@ func (m *MsgSysCreateAcquireSemaphore) Opcode() network.PacketID { func (m *MsgSysCreateAcquireSemaphore) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint16() - if _config.ErupeConfig.ClientID >= _config.S7 { // Assuming this was added with Ravi? + if config.GetConfig().ClientID >= config.S7 { // Assuming this was added with Ravi? m.PlayerCount = bf.ReadUint8() } bf.ReadUint8() // SemaphoreID length diff --git a/network/mhfpacket/msg_sys_create_semaphore.go b/network/mhfpacket/msg_sys_create_semaphore.go index 74fc58b12..fa7136e88 100644 --- a/network/mhfpacket/msg_sys_create_semaphore.go +++ b/network/mhfpacket/msg_sys_create_semaphore.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -25,7 +25,7 @@ func (m *MsgSysCreateSemaphore) Opcode() network.PacketID { func (m *MsgSysCreateSemaphore) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint16() - if _config.ErupeConfig.ClientID >= _config.S7 { // Assuming this was added with Ravi? + if config.GetConfig().ClientID >= config.S7 { // Assuming this was added with Ravi? m.PlayerCount = bf.ReadUint8() } bf.ReadUint8() // SemaphoreID length diff --git a/network/mhfpacket/msg_sys_terminal_log.go b/network/mhfpacket/msg_sys_terminal_log.go index b7eed3e9f..cff8c0dc2 100644 --- a/network/mhfpacket/msg_sys_terminal_log.go +++ b/network/mhfpacket/msg_sys_terminal_log.go @@ -2,7 +2,7 @@ package mhfpacket import ( "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/byteframe" @@ -48,7 +48,7 @@ func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame) error { e.Unk1 = bf.ReadInt32() e.Unk2 = bf.ReadInt32() e.Unk3 = bf.ReadInt32() - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { for j := 0; j < 4; j++ { e.Unk4 = append(e.Unk4, bf.ReadInt32()) } diff --git a/server/api/api_server.go b/server/api/api_server.go index 19798837e..405657dd6 100644 --- a/server/api/api_server.go +++ b/server/api/api_server.go @@ -2,7 +2,7 @@ package api import ( "context" - _config "erupe-ce/config" + "erupe-ce/config" "fmt" "net/http" "os" @@ -13,33 +13,24 @@ import ( "github.com/gorilla/handlers" "github.com/gorilla/mux" - "github.com/jmoiron/sqlx" "go.uber.org/zap" ) -type Config struct { - DB *sqlx.DB - ErupeConfig *_config.Config -} - // APIServer is Erupes Standard API interface type APIServer struct { sync.Mutex logger logger.Logger - erupeConfig *_config.Config - db *sqlx.DB + erupeConfig *config.Config httpServer *http.Server isShuttingDown bool } // NewAPIServer creates a new Server type. -func NewAPIServer(config *Config) *APIServer { +func NewAPIServer() *APIServer { s := &APIServer{ - logger: logger.Get().Named("API"), - erupeConfig: config.ErupeConfig, - db: config.DB, - httpServer: &http.Server{}, + logger: logger.Get().Named("API"), + httpServer: &http.Server{}, } return s } @@ -58,7 +49,7 @@ func (s *APIServer) Start() error { r.HandleFunc("/api/ss/bbs/{id}", s.ScreenShotGet) handler := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}))(r) s.httpServer.Handler = handlers.LoggingHandler(os.Stdout, handler) - s.httpServer.Addr = fmt.Sprintf(":%d", s.erupeConfig.API.Port) + s.httpServer.Addr = fmt.Sprintf(":%d", config.GetConfig().API.Port) serveError := make(chan error, 1) go func() { diff --git a/server/api/dbutils.go b/server/api/dbutils.go index 349711e6c..fce7744a0 100644 --- a/server/api/dbutils.go +++ b/server/api/dbutils.go @@ -3,6 +3,7 @@ package api import ( "context" "database/sql" + "erupe-ce/utils/db" "erupe-ce/utils/token" "fmt" "time" @@ -21,7 +22,11 @@ func (s *APIServer) createNewUser(ctx context.Context, username string, password id uint32 rights uint32 ) - err = s.db.QueryRowContext( + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRowContext( ctx, ` INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3) @@ -35,7 +40,11 @@ func (s *APIServer) createNewUser(ctx context.Context, username string, password func (s *APIServer) createLoginToken(ctx context.Context, uid uint32) (uint32, string, error) { loginToken := token.Generate(16) var tid uint32 - err := s.db.QueryRowContext(ctx, "INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id", uid, loginToken).Scan(&tid) + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRowContext(ctx, "INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id", uid, loginToken).Scan(&tid) if err != nil { return 0, "", err } @@ -44,7 +53,11 @@ func (s *APIServer) createLoginToken(ctx context.Context, uid uint32) (uint32, s func (s *APIServer) userIDFromToken(ctx context.Context, token string) (uint32, error) { var userID uint32 - err := s.db.QueryRowContext(ctx, "SELECT user_id FROM sign_sessions WHERE token = $1", token).Scan(&userID) + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRowContext(ctx, "SELECT user_id FROM sign_sessions WHERE token = $1", token).Scan(&userID) if err == sql.ErrNoRows { return 0, fmt.Errorf("invalid login token") } else if err != nil { @@ -55,17 +68,21 @@ func (s *APIServer) userIDFromToken(ctx context.Context, token string) (uint32, func (s *APIServer) createCharacter(ctx context.Context, userID uint32) (Character, error) { var character Character - err := s.db.GetContext(ctx, &character, + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.GetContext(ctx, &character, "SELECT id, name, is_female, weapon_type, hr, gr, last_login FROM characters WHERE is_new_character = true AND user_id = $1 LIMIT 1", userID, ) if err == sql.ErrNoRows { var count int - s.db.QueryRowContext(ctx, "SELECT COUNT(*) FROM characters WHERE user_id = $1", userID).Scan(&count) + database.QueryRowContext(ctx, "SELECT COUNT(*) FROM characters WHERE user_id = $1", userID).Scan(&count) if count >= 16 { return character, fmt.Errorf("cannot have more than 16 characters") } - err = s.db.GetContext(ctx, &character, ` + err = database.GetContext(ctx, &character, ` INSERT INTO characters ( user_id, is_female, is_new_character, name, unk_desc_string, hr, gr, weapon_type, last_login @@ -80,21 +97,29 @@ func (s *APIServer) createCharacter(ctx context.Context, userID uint32) (Charact func (s *APIServer) deleteCharacter(ctx context.Context, userID uint32, charID uint32) error { var isNew bool - err := s.db.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", charID).Scan(&isNew) + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", charID).Scan(&isNew) if err != nil { return err } if isNew { - _, err = s.db.Exec("DELETE FROM characters WHERE id = $1", charID) + _, err = database.Exec("DELETE FROM characters WHERE id = $1", charID) } else { - _, err = s.db.Exec("UPDATE characters SET deleted = true WHERE id = $1", charID) + _, err = database.Exec("UPDATE characters SET deleted = true WHERE id = $1", charID) } return err } func (s *APIServer) getCharactersForUser(ctx context.Context, uid uint32) ([]Character, error) { var characters []Character - err := s.db.SelectContext( + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.SelectContext( ctx, &characters, ` SELECT id, name, is_female, weapon_type, hr, gr, last_login FROM characters @@ -109,25 +134,33 @@ func (s *APIServer) getCharactersForUser(ctx context.Context, uid uint32) ([]Cha func (s *APIServer) getReturnExpiry(uid uint32) time.Time { var returnExpiry, lastLogin time.Time - s.db.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid) + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid) if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) { returnExpiry = time.Now().Add(time.Hour * 24 * 30) - s.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) + database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) } else { - err := s.db.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid) + err := database.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid) if err != nil { returnExpiry = time.Now() - s.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) + database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) } } - s.db.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid) + database.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid) return returnExpiry } func (s *APIServer) exportSave(ctx context.Context, uid uint32, cid uint32) (map[string]interface{}, error) { - row := s.db.QueryRowxContext(ctx, "SELECT * FROM characters WHERE id=$1 AND user_id=$2", cid, uid) + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + row := database.QueryRowxContext(ctx, "SELECT * FROM characters WHERE id=$1 AND user_id=$2", cid, uid) result := make(map[string]interface{}) - err := row.MapScan(result) + err = row.MapScan(result) if err != nil { return nil, err } diff --git a/server/api/endpoints.go b/server/api/endpoints.go index 8d5404088..bc425dce5 100644 --- a/server/api/endpoints.go +++ b/server/api/endpoints.go @@ -5,7 +5,8 @@ import ( "encoding/json" "encoding/xml" "errors" - _config "erupe-ce/config" + "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "fmt" "image" @@ -30,9 +31,9 @@ const ( ) type LauncherResponse struct { - Banners []_config.APISignBanner `json:"banners"` - Messages []_config.APISignMessage `json:"messages"` - Links []_config.APISignLink `json:"links"` + Banners []config.APISignBanner `json:"banners"` + Messages []config.APISignMessage `json:"messages"` + Links []config.APISignLink `json:"links"` } type User struct { @@ -137,7 +138,11 @@ func (s *APIServer) Login(w http.ResponseWriter, r *http.Request) { userRights uint32 password string ) - err := s.db.QueryRow("SELECT id, password, rights FROM users WHERE username = $1", reqData.Username).Scan(&userID, &password, &userRights) + database, err := db.GetDB() + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT id, password, rights FROM users WHERE username = $1", reqData.Username).Scan(&userID, &password, &userRights) if err == sql.ErrNoRows { w.WriteHeader(400) w.Write([]byte("username-error")) diff --git a/server/channelserver/ack_helpers.go b/server/channelserver/ack_helpers.go index 4e34a69e6..291926846 100644 --- a/server/channelserver/ack_helpers.go +++ b/server/channelserver/ack_helpers.go @@ -1,23 +1,24 @@ package channelserver import ( + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" ) -func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) { +func DoAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) { bf := byteframe.NewByteFrame() - bf.WriteUint32(uint32(s.server.erupeConfig.EarthID)) + bf.WriteUint32(uint32(config.GetConfig().EarthID)) bf.WriteUint32(0) bf.WriteUint32(0) bf.WriteUint32(uint32(len(data))) for i := range data { bf.WriteBytes(data[i].Data()) } - doAckBufSucceed(s, ackHandle, bf.Data()) + DoAckBufSucceed(s, ackHandle, bf.Data()) } -func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) { +func DoAckBufSucceed(s *Session, ackHandle uint32, data []byte) { s.QueueSendMHF(&mhfpacket.MsgSysAck{ AckHandle: ackHandle, IsBufferResponse: true, @@ -26,7 +27,7 @@ func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) { }) } -func doAckBufFail(s *Session, ackHandle uint32, data []byte) { +func DoAckBufFail(s *Session, ackHandle uint32, data []byte) { s.QueueSendMHF(&mhfpacket.MsgSysAck{ AckHandle: ackHandle, IsBufferResponse: true, @@ -35,7 +36,7 @@ func doAckBufFail(s *Session, ackHandle uint32, data []byte) { }) } -func doAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) { +func DoAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) { s.QueueSendMHF(&mhfpacket.MsgSysAck{ AckHandle: ackHandle, IsBufferResponse: false, @@ -44,7 +45,7 @@ func doAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) { }) } -func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) { +func DoAckSimpleFail(s *Session, ackHandle uint32, data []byte) { s.QueueSendMHF(&mhfpacket.MsgSysAck{ AckHandle: ackHandle, IsBufferResponse: false, diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index c988ddb75..b42ed0321 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -2,7 +2,8 @@ package channelserver import ( "encoding/binary" - _config "erupe-ce/config" + "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/mhfcourse" "erupe-ce/utils/mhfitem" @@ -28,12 +29,16 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) { enumBf := byteframe.NewByteFrame() enumBf.WriteUint32(0) // Entry count (count for quests, rankings, events, etc.) - doAckBufSucceed(s, ackHandle, enumBf.Data()) + DoAckBufSucceed(s, ackHandle, enumBf.Data()) } func updateRights(s *Session) { rightsInt := uint32(2) - s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&rightsInt) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.CharID).Scan(&rightsInt) s.courses, rightsInt = mhfcourse.GetCourseStruct(rightsInt) update := &mhfpacket.MsgSysUpdateRight{ ClientRespAckHandle: 0, @@ -63,7 +68,7 @@ func handleMsgSysAck(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysTerminalLog) for i := range pkt.Entries { - s.server.logger.Info("SysTerminalLog", + s.Server.logger.Info("SysTerminalLog", zap.Uint8("Type1", pkt.Entries[i].Type1), zap.Uint8("Type2", pkt.Entries[i].Type2), zap.Int16("Unk0", pkt.Entries[i].Unk0), @@ -75,55 +80,58 @@ func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) { } resp := byteframe.NewByteFrame() resp.WriteUint32(pkt.LogID + 1) // LogID to use for requests after this. - doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLogin) - - if !s.server.erupeConfig.DebugOptions.DisableTokenCheck { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + if !config.GetConfig().DebugOptions.DisableTokenCheck { var token string - err := s.server.db.QueryRow("SELECT token FROM sign_sessions ss INNER JOIN public.users u on ss.user_id = u.id WHERE token=$1 AND ss.id=$2 AND u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.LoginTokenString, pkt.LoginTokenNumber, pkt.CharID0).Scan(&token) + err := database.QueryRow("SELECT token FROM sign_sessions ss INNER JOIN public.users u on ss.user_id = u.id WHERE token=$1 AND ss.id=$2 AND u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.LoginTokenString, pkt.LoginTokenNumber, pkt.CharID0).Scan(&token) if err != nil { s.rawConn.Close() - s.logger.Warn(fmt.Sprintf("Invalid login token, offending CID: (%d)", pkt.CharID0)) + s.Logger.Warn(fmt.Sprintf("Invalid login token, offending CID: (%d)", pkt.CharID0)) return } } s.Lock() - s.charID = pkt.CharID0 + s.CharID = pkt.CharID0 s.token = pkt.LoginTokenString s.Unlock() bf := byteframe.NewByteFrame() bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) // Unix timestamp - _, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.server.sessions), s.server.ID) + _, err = database.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.Server.sessions), s.Server.ID) if err != nil { panic(err) } - _, err = s.server.db.Exec("UPDATE sign_sessions SET server_id=$1, char_id=$2 WHERE token=$3", s.server.ID, s.charID, s.token) + _, err = database.Exec("UPDATE sign_sessions SET server_id=$1, char_id=$2 WHERE token=$3", s.Server.ID, s.CharID, s.token) if err != nil { panic(err) } - _, err = s.server.db.Exec("UPDATE characters SET last_login=$1 WHERE id=$2", gametime.TimeAdjusted().Unix(), s.charID) + _, err = database.Exec("UPDATE characters SET last_login=$1 WHERE id=$2", gametime.TimeAdjusted().Unix(), s.CharID) if err != nil { panic(err) } - _, err = s.server.db.Exec("UPDATE users u SET last_character=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.charID) + _, err = database.Exec("UPDATE users u SET last_character=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.CharID) if err != nil { panic(err) } - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) updateRights(s) - s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{CharID: s.charID}, s) + s.Server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{CharID: s.CharID}, s) } func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) { @@ -131,45 +139,49 @@ func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) { } func logoutPlayer(s *Session) { - s.server.Lock() - if _, exists := s.server.sessions[s.rawConn]; exists { - delete(s.server.sessions, s.rawConn) + + s.Server.Lock() + if _, exists := s.Server.sessions[s.rawConn]; exists { + delete(s.Server.sessions, s.rawConn) } s.rawConn.Close() - delete(s.server.objectIDs, s) - s.server.Unlock() + delete(s.Server.objectIDs, s) + s.Server.Unlock() - for _, stage := range s.server.stages { + for _, stage := range s.Server.stages { // Tell sessions registered to disconnecting players quest to unregister - if stage.host != nil && stage.host.charID == s.charID { - for _, sess := range s.server.sessions { + if stage.host != nil && stage.host.CharID == s.CharID { + for _, sess := range s.Server.sessions { for rSlot := range stage.reservedClientSlots { - if sess.charID == rSlot && sess.stage != nil && sess.stage.id[3:5] != "Qs" { + if sess.CharID == rSlot && sess.stage != nil && sess.stage.id[3:5] != "Qs" { sess.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) } } } } for session := range stage.clients { - if session.charID == s.charID { + if session.CharID == s.CharID { delete(stage.clients, session) } } } - - _, err := s.server.db.Exec("UPDATE sign_sessions SET server_id=NULL, char_id=NULL WHERE token=$1", s.token) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec("UPDATE sign_sessions SET server_id=NULL, char_id=NULL WHERE token=$1", s.token) if err != nil { panic(err) } - _, err = s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.server.sessions), s.server.ID) + _, err = database.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.Server.sessions), s.Server.ID) if err != nil { panic(err) } var timePlayed int var sessionTime int - _ = s.server.db.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.charID).Scan(&timePlayed) + _ = database.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.CharID).Scan(&timePlayed) sessionTime = int(gametime.TimeAdjusted().Unix()) - int(s.sessionStart) timePlayed += sessionTime @@ -177,43 +189,43 @@ func logoutPlayer(s *Session) { if mhfcourse.CourseExists(30, s.courses) { rpGained = timePlayed / 900 timePlayed = timePlayed % 900 - s.server.db.Exec("UPDATE characters SET cafe_time=cafe_time+$1 WHERE id=$2", sessionTime, s.charID) + database.Exec("UPDATE characters SET cafe_time=cafe_time+$1 WHERE id=$2", sessionTime, s.CharID) } else { rpGained = timePlayed / 1800 timePlayed = timePlayed % 1800 } - s.server.db.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.charID) + database.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.CharID) - s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE character_id=$1`, s.charID) + database.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE character_id=$1`, s.CharID) if s.stage == nil { return } - s.server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser{ - CharID: s.charID, + s.Server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser{ + CharID: s.CharID, }, s) - s.server.Lock() - for _, stage := range s.server.stages { - if _, exists := stage.reservedClientSlots[s.charID]; exists { - delete(stage.reservedClientSlots, s.charID) + s.Server.Lock() + for _, stage := range s.Server.stages { + if _, exists := stage.reservedClientSlots[s.CharID]; exists { + delete(stage.reservedClientSlots, s.CharID) } } - s.server.Unlock() + s.Server.Unlock() removeSessionFromSemaphore(s) removeSessionFromStage(s) - saveData, err := GetCharacterSaveData(s, s.charID) + saveData, err := GetCharacterSaveData(s, s.CharID) if err != nil || saveData == nil { - s.logger.Error("Failed to get savedata") + s.Logger.Error("Failed to get savedata") return } saveData.RP += uint16(rpGained) - if saveData.RP >= s.server.erupeConfig.GameplayOptions.MaximumRP { - saveData.RP = s.server.erupeConfig.GameplayOptions.MaximumRP + if saveData.RP >= config.GetConfig().GameplayOptions.MaximumRP { + saveData.RP = config.GetConfig().GameplayOptions.MaximumRP } saveData.Save(s) } @@ -222,7 +234,7 @@ func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysPing(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysPing) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgSysTime(s *Session, p mhfpacket.MHFPacket) { @@ -253,25 +265,29 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) { // Issue it. resp := byteframe.NewByteFrame() resp.WriteBytes(logKey) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysRecordLog) - if _config.ErupeConfig.ClientID == _config.ZZ { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + if config.GetConfig().ClientID == config.ZZ { bf := byteframe.NewByteFrameFromBytes(pkt.Data) bf.Seek(32, 0) var val uint8 for i := 0; i < 176; i++ { val = bf.ReadUint8() if val > 0 && mhfmon.Monsters[i].Large { - s.server.db.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.charID, i, val, gametime.TimeAdjusted()) + database.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.CharID, i, val, gametime.TimeAdjusted()) } } } // remove a client returning to town from reserved slots to make sure the stage is hidden from board - delete(s.stage.reservedClientSlots, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + delete(s.stage.reservedClientSlots, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {} @@ -279,7 +295,7 @@ func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLockGlobalSema) var sgid string - for _, channel := range s.server.Channels { + for _, channel := range s.Server.Channels { for id := range channel.stages { if strings.HasSuffix(id, pkt.UserIDString) { sgid = channel.GlobalID @@ -287,7 +303,7 @@ func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) { } } bf := byteframe.NewByteFrame() - if len(sgid) > 0 && sgid != s.server.GlobalID { + if len(sgid) > 0 && sgid != s.Server.GlobalID { bf.WriteUint8(0) bf.WriteUint8(0) ps.Uint16(bf, sgid, false) @@ -296,12 +312,12 @@ func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(0) ps.Uint16(bf, pkt.ServerChannelIDString, false) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgSysUnlockGlobalSema(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysUnlockGlobalSema) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgSysUpdateRight(s *Session, p mhfpacket.MHFPacket) {} @@ -313,7 +329,7 @@ func handleMsgSysAuthTerminal(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysRightsReload(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysRightsReload) updateRights(s) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { @@ -351,18 +367,18 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint16(0) switch pkt.SearchType { case 1, 2, 3: // usersearchidx, usersearchname, lobbysearchname - for _, c := range s.server.Channels { + for _, c := range s.Server.Channels { for _, session := range c.sessions { if count == maxResults { break } - if pkt.SearchType == 1 && session.charID != cid { + if pkt.SearchType == 1 && session.CharID != cid { continue } if pkt.SearchType == 2 && !strings.Contains(session.Name, term) { continue } - if pkt.SearchType == 3 && session.server.IP != ip && session.server.Port != port && session.stage.id != term { + if pkt.SearchType == 3 && session.Server.IP != ip && session.Server.Port != port && session.stage.id != term { continue } count++ @@ -374,13 +390,13 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(0x0100007F) } resp.WriteUint16(c.Port) - resp.WriteUint32(session.charID) + resp.WriteUint32(session.CharID) resp.WriteUint8(uint8(len(sessionStage) + 1)) resp.WriteUint8(uint8(len(sessionName) + 1)) - resp.WriteUint16(uint16(len(c.userBinaryParts[userBinaryPartID{charID: session.charID, index: 3}]))) + resp.WriteUint16(uint16(len(c.userBinaryParts[userBinaryPartID{charID: session.CharID, index: 3}]))) // TODO: This case might be <=G2 - if _config.ErupeConfig.ClientID <= _config.G1 { + if config.GetConfig().ClientID <= config.G1 { resp.WriteBytes(make([]byte, 8)) } else { resp.WriteBytes(make([]byte, 40)) @@ -389,7 +405,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { resp.WriteNullTerminatedBytes(sessionStage) resp.WriteNullTerminatedBytes(sessionName) - resp.WriteBytes(c.userBinaryParts[userBinaryPartID{session.charID, 3}]) + resp.WriteBytes(c.userBinaryParts[userBinaryPartID{session.CharID, 3}]) } } case 4: // lobbysearch @@ -411,7 +427,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { case 0: values := bf.ReadUint8() for i := uint8(0); i < values; i++ { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { findPartyParams.RankRestriction = bf.ReadInt16() } else { findPartyParams.RankRestriction = int16(bf.ReadInt8()) @@ -420,7 +436,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { case 1: values := bf.ReadUint8() for i := uint8(0); i < values; i++ { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { findPartyParams.Targets = append(findPartyParams.Targets, bf.ReadInt16()) } else { findPartyParams.Targets = append(findPartyParams.Targets, int16(bf.ReadInt8())) @@ -430,7 +446,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { values := bf.ReadUint8() for i := uint8(0); i < values; i++ { var value int16 - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { value = bf.ReadInt16() } else { value = int16(bf.ReadInt8()) @@ -451,7 +467,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { case 3: // Unknown values := bf.ReadUint8() for i := uint8(0); i < values; i++ { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { findPartyParams.Unk0 = append(findPartyParams.Unk0, bf.ReadInt16()) } else { findPartyParams.Unk0 = append(findPartyParams.Unk0, int16(bf.ReadInt8())) @@ -460,7 +476,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { case 4: // Looking for n or already have n values := bf.ReadUint8() for i := uint8(0); i < values; i++ { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { findPartyParams.Unk1 = append(findPartyParams.Unk1, bf.ReadInt16()) } else { findPartyParams.Unk1 = append(findPartyParams.Unk1, int16(bf.ReadInt8())) @@ -469,7 +485,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { case 5: values := bf.ReadUint8() for i := uint8(0); i < values; i++ { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { findPartyParams.QuestID = append(findPartyParams.QuestID, bf.ReadInt16()) } else { findPartyParams.QuestID = append(findPartyParams.QuestID, int16(bf.ReadInt8())) @@ -477,7 +493,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { } } } - for _, c := range s.server.Channels { + for _, c := range s.Server.Channels { for _, stage := range c.stages { if count == maxResults { break @@ -487,15 +503,15 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { sb3.Seek(4, 0) stageDataParams := 7 - if _config.ErupeConfig.ClientID <= _config.G10 { + if config.GetConfig().ClientID <= config.G10 { stageDataParams = 4 - } else if _config.ErupeConfig.ClientID <= _config.Z1 { + } else if config.GetConfig().ClientID <= config.Z1 { stageDataParams = 6 } var stageData []int16 for i := 0; i < stageDataParams; i++ { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { stageData = append(stageData, sb3.ReadInt16()) } else { stageData = append(stageData, int16(sb3.ReadInt8())) @@ -544,7 +560,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 1}]))) for i := range stageData { - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { resp.WriteInt16(stageData[i]) } else { resp.WriteInt8(int8(stageData[i])) @@ -562,7 +578,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { } resp.Seek(0, io.SeekStart) resp.WriteUint16(count) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgCaExchangeItem(s *Session, p mhfpacket.MHFPacket) {} @@ -571,8 +587,8 @@ func handleMsgMhfServerCommand(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfAnnounce(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAnnounce) - s.server.BroadcastRaviente(pkt.IPAddress, pkt.Port, pkt.StageID, pkt.Data.ReadUint8()) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Server.BroadcastRaviente(pkt.IPAddress, pkt.Port, pkt.StageID, pkt.Data.ReadUint8()) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfSetLoginwindow(s *Session, p mhfpacket.MHFPacket) {} @@ -595,7 +611,7 @@ func handleMsgMhfGetCaUniqueID(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfTransferItem) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) { @@ -760,7 +776,7 @@ func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(gz.Unk3) bf.WriteUint8(gz.Unk4) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) { @@ -773,7 +789,11 @@ func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {} func userGetItems(s *Session) []mhfitem.MHFItemStack { var data []byte var items []mhfitem.MHFItemStack - s.server.db.QueryRow(`SELECT item_box FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow(`SELECT item_box FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&data) if len(data) > 0 { box := byteframe.NewByteFrameFromBytes(data) numStacks := box.ReadUint16() @@ -790,14 +810,18 @@ func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) { items := userGetItems(s) bf := byteframe.NewByteFrame() bf.WriteBytes(mhfitem.SerializeWarehouseItems(items)) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem) newStacks := mhfitem.DiffItemStacks(userGetItems(s), pkt.UpdatedItems) - s.server.db.Exec(`UPDATE users u SET item_box=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, mhfitem.SerializeWarehouseItems(newStacks), s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE users u SET item_box=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, mhfitem.SerializeWarehouseItems(newStacks), s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfGetCogInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -806,20 +830,24 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCheckWeeklyStamp) var total, redeemed, updated uint16 var lastCheck time.Time - err := s.server.db.QueryRow(fmt.Sprintf("SELECT %s_checked FROM stamps WHERE character_id=$1", pkt.StampType), s.charID).Scan(&lastCheck) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow(fmt.Sprintf("SELECT %s_checked FROM stamps WHERE character_id=$1", pkt.StampType), s.CharID).Scan(&lastCheck) if err != nil { lastCheck = gametime.TimeAdjusted() - s.server.db.Exec("INSERT INTO stamps (character_id, hl_checked, ex_checked) VALUES ($1, $2, $2)", s.charID, gametime.TimeAdjusted()) + database.Exec("INSERT INTO stamps (character_id, hl_checked, ex_checked) VALUES ($1, $2, $2)", s.CharID, gametime.TimeAdjusted()) } else { - s.server.db.Exec(fmt.Sprintf(`UPDATE stamps SET %s_checked=$1 WHERE character_id=$2`, pkt.StampType), gametime.TimeAdjusted(), s.charID) + database.Exec(fmt.Sprintf(`UPDATE stamps SET %s_checked=$1 WHERE character_id=$2`, pkt.StampType), gametime.TimeAdjusted(), s.CharID) } if lastCheck.Before(gametime.TimeWeekStart()) { - s.server.db.Exec(fmt.Sprintf("UPDATE stamps SET %s_total=%s_total+1 WHERE character_id=$1", pkt.StampType, pkt.StampType), s.charID) + database.Exec(fmt.Sprintf("UPDATE stamps SET %s_total=%s_total+1 WHERE character_id=$1", pkt.StampType, pkt.StampType), s.CharID) updated = 1 } - s.server.db.QueryRow(fmt.Sprintf("SELECT %s_total, %s_redeemed FROM stamps WHERE character_id=$1", pkt.StampType, pkt.StampType), s.charID).Scan(&total, &redeemed) + database.QueryRow(fmt.Sprintf("SELECT %s_total, %s_redeemed FROM stamps WHERE character_id=$1", pkt.StampType, pkt.StampType), s.CharID).Scan(&total, &redeemed) bf := byteframe.NewByteFrame() bf.WriteUint16(total) bf.WriteUint16(redeemed) @@ -827,18 +855,22 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(0) bf.WriteUint16(0) bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix())) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfExchangeWeeklyStamp) var total, redeemed uint16 var tktStack mhfitem.MHFItemStack + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.Unk1 == 10 { // Yearly Sub Ex - s.server.db.QueryRow("UPDATE stamps SET hl_total=hl_total-48, hl_redeemed=hl_redeemed-48 WHERE character_id=$1 RETURNING hl_total, hl_redeemed", s.charID).Scan(&total, &redeemed) + database.QueryRow("UPDATE stamps SET hl_total=hl_total-48, hl_redeemed=hl_redeemed-48 WHERE character_id=$1 RETURNING hl_total, hl_redeemed", s.CharID).Scan(&total, &redeemed) tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 2210}, Quantity: 1} } else { - s.server.db.QueryRow(fmt.Sprintf("UPDATE stamps SET %s_redeemed=%s_redeemed+8 WHERE character_id=$1 RETURNING %s_total, %s_redeemed", pkt.StampType, pkt.StampType, pkt.StampType, pkt.StampType), s.charID).Scan(&total, &redeemed) + database.QueryRow(fmt.Sprintf("UPDATE stamps SET %s_redeemed=%s_redeemed+8 WHERE character_id=$1 RETURNING %s_total, %s_redeemed", pkt.StampType, pkt.StampType, pkt.StampType, pkt.StampType), s.CharID).Scan(&total, &redeemed) if pkt.StampType == "hl" { tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 1630}, Quantity: 5} } else { @@ -853,16 +885,20 @@ func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(tktStack.Item.ItemID) bf.WriteUint16(tktStack.Quantity) bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix())) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func getGoocooData(s *Session, cid uint32) [][]byte { var goocoo []byte var goocoos [][]byte + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } for i := 0; i < 5; i++ { - err := s.server.db.QueryRow(fmt.Sprintf("SELECT goocoo%d FROM goocoo WHERE id=$1", i), cid).Scan(&goocoo) + err := database.QueryRow(fmt.Sprintf("SELECT goocoo%d FROM goocoo WHERE id=$1", i), cid).Scan(&goocoo) if err != nil { - s.server.db.Exec("INSERT INTO goocoo (id) VALUES ($1)", s.charID) + database.Exec("INSERT INTO goocoo (id) VALUES ($1)", s.CharID) return goocoos } if err == nil && goocoo != nil { @@ -875,20 +911,24 @@ func getGoocooData(s *Session, cid uint32) [][]byte { func handleMsgMhfEnumerateGuacot(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuacot) bf := byteframe.NewByteFrame() - goocoos := getGoocooData(s, s.charID) + goocoos := getGoocooData(s, s.CharID) bf.WriteUint16(uint16(len(goocoos))) bf.WriteUint16(0) for _, goocoo := range goocoos { bf.WriteBytes(goocoo) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateGuacot) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } for _, goocoo := range pkt.Goocoos { if goocoo.Data1[0] == 0 { - s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=NULL WHERE id=$1", goocoo.Index), s.charID) + database.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=NULL WHERE id=$1", goocoo.Index), s.CharID) } else { bf := byteframe.NewByteFrame() bf.WriteUint32(goocoo.Index) @@ -900,11 +940,11 @@ func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint8(uint8(len(goocoo.Name))) bf.WriteBytes(goocoo.Name) - s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=$1 WHERE id=$2", goocoo.Index), bf.Data(), s.charID) + database.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=$1 WHERE id=$2", goocoo.Index), bf.Data(), s.CharID) dumpSaveData(s, bf.Data(), fmt.Sprintf("goocoo-%d", goocoo.Index)) } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type Scenario struct { @@ -921,11 +961,15 @@ func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfInfoScenarioCounter) var scenarios []Scenario var scenario Scenario - scenarioData, err := s.server.db.Queryx("SELECT scenario_id, category_id FROM scenario_counter") + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + scenarioData, err := database.Queryx("SELECT scenario_id, category_id FROM scenario_counter") if err != nil { scenarioData.Close() - s.logger.Error("Failed to get scenario counter info from db", zap.Error(err)) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + s.Logger.Error("Failed to get scenario counter info from db", zap.Error(err)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } for scenarioData.Next() { @@ -954,26 +998,29 @@ func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint8(scenario.CategoryID) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEtcPoints) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var dailyTime time.Time - _ = s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime) + _ = database.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.CharID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime) if gametime.TimeAdjusted().After(dailyTime) { - s.server.db.Exec("UPDATE characters SET bonus_quests = 0, daily_quests = 0 WHERE id=$1", s.charID) + database.Exec("UPDATE characters SET bonus_quests = 0, daily_quests = 0 WHERE id=$1", s.CharID) } var bonusQuests, dailyQuests, promoPoints uint32 - _ = s.server.db.QueryRow(`SELECT bonus_quests, daily_quests, promo_points FROM characters WHERE id = $1`, s.charID).Scan(&bonusQuests, &dailyQuests, &promoPoints) + _ = database.QueryRow(`SELECT bonus_quests, daily_quests, promo_points FROM characters WHERE id = $1`, s.CharID).Scan(&bonusQuests, &dailyQuests, &promoPoints) resp := byteframe.NewByteFrame() resp.WriteUint8(3) // Maybe a count of uint32(s)? resp.WriteUint32(bonusQuests) resp.WriteUint32(dailyQuests) resp.WriteUint32(promoPoints) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) { @@ -988,17 +1035,20 @@ func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) { case 2: column = "promo_points" } - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var value int16 - err := s.server.db.QueryRow(fmt.Sprintf(`SELECT %s FROM characters WHERE id = $1`, column), s.charID).Scan(&value) + err = database.QueryRow(fmt.Sprintf(`SELECT %s FROM characters WHERE id = $1`, column), s.CharID).Scan(&value) if err == nil { if value+pkt.Delta < 0 { - s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = 0 WHERE id = $1`, column), s.charID) + database.Exec(fmt.Sprintf(`UPDATE characters SET %s = 0 WHERE id = $1`, column), s.CharID) } else { - s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = %s + $1 WHERE id = $2`, column, column), pkt.Delta, s.charID) + database.Exec(fmt.Sprintf(`UPDATE characters SET %s = %s + $1 WHERE id = $2`, column, column), pkt.Delta, s.CharID) } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) { @@ -1017,7 +1067,7 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) { {300, 5392, 1, 5392, 3}, {999, 5392, 1, 5392, 4}, } - if _config.ErupeConfig.ClientID <= _config.Z1 { + if config.GetConfig().ClientID <= config.Z1 { for _, reward := range rewards { if pkt.HR >= reward.HR { pkt.Item1 = reward.Item1 @@ -1030,12 +1080,16 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() bf.WriteUint16(pkt.HR) - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { bf.WriteUint16(pkt.GR) } var stamps, rewardTier, rewardUnk uint16 reward := mhfitem.MHFItemStack{Item: mhfitem.MHFItem{}} - s.server.db.QueryRow(`UPDATE characters SET stampcard = stampcard + $1 WHERE id = $2 RETURNING stampcard`, pkt.Stamps, s.charID).Scan(&stamps) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow(`UPDATE characters SET stampcard = stampcard + $1 WHERE id = $2 RETURNING stampcard`, pkt.Stamps, s.CharID).Scan(&stamps) bf.WriteUint16(stamps - pkt.Stamps) bf.WriteUint16(stamps) @@ -1055,14 +1109,14 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(rewardUnk) bf.WriteUint16(reward.Item.ItemID) bf.WriteUint16(reward.Quantity) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfStampcardPrize(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUnreserveSrg) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} @@ -1072,10 +1126,10 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix())) // Start bf.WriteUint32(uint32(gametime.TimeWeekNext().Unix())) // End - bf.WriteInt32(s.server.erupeConfig.EarthStatus) - bf.WriteInt32(s.server.erupeConfig.EarthID) - for i, m := range s.server.erupeConfig.EarthMonsters { - if _config.ErupeConfig.ClientID <= _config.G9 { + bf.WriteInt32(config.GetConfig().EarthStatus) + bf.WriteInt32(config.GetConfig().EarthID) + for i, m := range config.GetConfig().EarthMonsters { + if config.GetConfig().ClientID <= config.G9 { if i == 3 { break } @@ -1085,7 +1139,7 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { } bf.WriteInt32(m) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {} @@ -1124,7 +1178,7 @@ func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { } data = append(data, bf) } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} @@ -1135,7 +1189,7 @@ func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) { for i := uint16(0); i < pkt.Results; i++ { bf.WriteUint32(0) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) { @@ -1143,7 +1197,7 @@ func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() bf.WriteUint16(0) bf.WriteUint16(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type SeibattleTimetable struct { @@ -1281,12 +1335,12 @@ func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostSeibattle) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfGetDailyMissionMaster(s *Session, p mhfpacket.MHFPacket) {} @@ -1297,10 +1351,10 @@ func handleMsgMhfSetDailyMissionPersonal(s *Session, p mhfpacket.MHFPacket) {} func equipSkinHistSize() int { size := 3200 - if _config.ErupeConfig.ClientID <= _config.Z2 { + if config.GetConfig().ClientID <= config.Z2 { size = 2560 } - if _config.ErupeConfig.ClientID <= _config.Z1 { + if config.GetConfig().ClientID <= config.Z1 { size = 1280 } return size @@ -1310,22 +1364,30 @@ func handleMsgMhfGetEquipSkinHist(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEquipSkinHist) size := equipSkinHistSize() var data []byte - err := s.server.db.QueryRow("SELECT COALESCE(skin_hist::bytea, $2::bytea) FROM characters WHERE id = $1", s.charID, make([]byte, size)).Scan(&data) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load skin_hist", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT COALESCE(skin_hist::bytea, $2::bytea) FROM characters WHERE id = $1", s.CharID, make([]byte, size)).Scan(&data) + if err != nil { + s.Logger.Error("Failed to load skin_hist", zap.Error(err)) data = make([]byte, size) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateEquipSkinHist) size := equipSkinHistSize() var data []byte - err := s.server.db.QueryRow("SELECT COALESCE(skin_hist, $2) FROM characters WHERE id = $1", s.charID, make([]byte, size)).Scan(&data) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get skin_hist", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT COALESCE(skin_hist, $2) FROM characters WHERE id = $1", s.CharID, make([]byte, size)).Scan(&data) + if err != nil { + s.Logger.Error("Failed to get skin_hist", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } @@ -1336,15 +1398,15 @@ func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) { bitInByte := bit % 8 data[startByte+byteInd] |= bits.Reverse8(1 << uint(bitInByte)) dumpSaveData(s, data, "skinhist") - s.server.db.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfGetUdShopCoin(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdShopCoin) bf := byteframe.NewByteFrame() bf.WriteUint32(0) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUseUdShopCoin(s *Session, p mhfpacket.MHFPacket) {} @@ -1353,22 +1415,30 @@ func handleMsgMhfGetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEnhancedMinidata) // this looks to be the detailed chunk of information you can pull up on players in town var data []byte - err := s.server.db.QueryRow("SELECT minidata FROM characters WHERE id = $1", pkt.CharID).Scan(&data) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load minidata") + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT minidata FROM characters WHERE id = $1", pkt.CharID).Scan(&data) + if err != nil { + s.Logger.Error("Failed to load minidata") data = make([]byte, 1) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetEnhancedMinidata) dumpSaveData(s, pkt.RawDataPayload, "minidata") - _, err := s.server.db.Exec("UPDATE characters SET minidata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to save minidata", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + _, err = database.Exec("UPDATE characters SET minidata=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) + if err != nil { + s.Logger.Error("Failed to save minidata", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfGetLobbyCrowd(s *Session, p mhfpacket.MHFPacket) { @@ -1378,7 +1448,7 @@ func handleMsgMhfGetLobbyCrowd(s *Session, p mhfpacket.MHFPacket) { // It can be worried about later if we ever get to the point where there are // full servers to actually need to migrate people from and empty ones to pkt := p.(*mhfpacket.MsgMhfGetLobbyCrowd) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x320)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x320)) } type TrendWeapon struct { @@ -1389,8 +1459,12 @@ type TrendWeapon struct { func handleMsgMhfGetTrendWeapon(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetTrendWeapon) trendWeapons := [14][3]TrendWeapon{} + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } for i := uint8(0); i < 14; i++ { - rows, err := s.server.db.Query(`SELECT weapon_id FROM trend_weapons WHERE weapon_type=$1 ORDER BY count DESC LIMIT 3`, i) + rows, err := database.Query(`SELECT weapon_id FROM trend_weapons WHERE weapon_type=$1 ORDER BY count DESC LIMIT 3`, i) if err != nil { continue } @@ -1414,12 +1488,16 @@ func handleMsgMhfGetTrendWeapon(s *Session, p mhfpacket.MHFPacket) { } bf.Seek(0, 0) bf.WriteUint8(x) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUpdateUseTrendWeaponLog(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateUseTrendWeaponLog) - s.server.db.Exec(`INSERT INTO trend_weapons (weapon_id, weapon_type, count) VALUES ($1, $2, 1) ON CONFLICT (weapon_id) DO + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`INSERT INTO trend_weapons (weapon_id, weapon_type, count) VALUES ($1, $2, 1) ON CONFLICT (weapon_id) DO UPDATE SET count = trend_weapons.count+1`, pkt.WeaponID, pkt.WeaponType) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_achievement.go b/server/channelserver/handlers_achievement.go index 9eb3b992a..e55e4657a 100644 --- a/server/channelserver/handlers_achievement.go +++ b/server/channelserver/handlers_achievement.go @@ -3,6 +3,7 @@ package channelserver import ( "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "fmt" "io" ) @@ -88,19 +89,23 @@ func handleMsgMhfGetAchievement(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetAchievement) var exists int - err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", pkt.CharID).Scan(&exists) + database, err := db.GetDB() if err != nil { - s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", pkt.CharID) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT id FROM achievements WHERE id=$1", pkt.CharID).Scan(&exists) + if err != nil { + database.Exec("INSERT INTO achievements (id) VALUES ($1)", pkt.CharID) } var scores [33]int32 - err = s.server.db.QueryRow("SELECT * FROM achievements WHERE id=$1", pkt.CharID).Scan(&scores[0], + err = database.QueryRow("SELECT * FROM achievements WHERE id=$1", pkt.CharID).Scan(&scores[0], &scores[0], &scores[1], &scores[2], &scores[3], &scores[4], &scores[5], &scores[6], &scores[7], &scores[8], &scores[9], &scores[10], &scores[11], &scores[12], &scores[13], &scores[14], &scores[15], &scores[16], &scores[17], &scores[18], &scores[19], &scores[20], &scores[21], &scores[22], &scores[23], &scores[24], &scores[25], &scores[26], &scores[27], &scores[28], &scores[29], &scores[30], &scores[31], &scores[32]) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 20)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 20)) return } @@ -136,26 +141,29 @@ func handleMsgMhfGetAchievement(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(points) resp.WriteUint32(points) resp.WriteUint32(points) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfSetCaAchievementHist(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetCaAchievementHist) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfResetAchievement(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfAddAchievement(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAddAchievement) - - var exists int - err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", s.charID).Scan(&exists) + database, err := db.GetDB() if err != nil { - s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", s.charID) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var exists int + err = database.QueryRow("SELECT id FROM achievements WHERE id=$1", s.CharID).Scan(&exists) + if err != nil { + database.Exec("INSERT INTO achievements (id) VALUES ($1)", s.CharID) } - s.server.db.Exec(fmt.Sprintf("UPDATE achievements SET ach%d=ach%d+1 WHERE id=$1", pkt.AchievementID, pkt.AchievementID), s.charID) + database.Exec(fmt.Sprintf("UPDATE achievements SET ach%d=ach%d+1 WHERE id=$1", pkt.AchievementID, pkt.AchievementID), s.CharID) } func handleMsgMhfPaymentAchievement(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_bbs.go b/server/channelserver/handlers_bbs.go index d350a38f4..38cee58a7 100644 --- a/server/channelserver/handlers_bbs.go +++ b/server/channelserver/handlers_bbs.go @@ -1,6 +1,7 @@ package channelserver import ( + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" "erupe-ce/utils/stringsupport" @@ -18,7 +19,7 @@ func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(0) bf.WriteUint32(0) bf.WriteUint32(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } // Checks the status of Bultin Board Server to see if authenticated @@ -29,7 +30,7 @@ func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(401) //unk http status? bf.WriteUint32(401) //unk http status? bf.WriteUint32(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } // Tells the game client what host port and gives the bultin board article a token @@ -39,15 +40,15 @@ func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) { articleToken := token.Generate(40) bf.WriteUint32(200) //http status //200 success //4XX An error occured server side - bf.WriteUint32(s.server.erupeConfig.Screenshots.Port) + bf.WriteUint32(config.GetConfig().Screenshots.Port) bf.WriteUint32(0) bf.WriteUint32(0) bf.WriteBytes(stringsupport.PaddedString(articleToken, 64, false)) - bf.WriteBytes(stringsupport.PaddedString(s.server.erupeConfig.Screenshots.Host, 64, false)) + bf.WriteBytes(stringsupport.PaddedString(config.GetConfig().Screenshots.Host, 64, false)) //pkt.unk1[3] == Changes sometimes? - if s.server.erupeConfig.Screenshots.Enabled && s.server.erupeConfig.Discord.Enabled { - s.server.DiscordScreenShotSend(pkt.Name, pkt.Title, pkt.Description, articleToken) + if config.GetConfig().Screenshots.Enabled && config.GetConfig().Discord.Enabled { + s.Server.DiscordScreenShotSend(pkt.Name, pkt.Title, pkt.Description, articleToken) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_cafe.go b/server/channelserver/handlers_cafe.go index 1b8238246..916af5abd 100644 --- a/server/channelserver/handlers_cafe.go +++ b/server/channelserver/handlers_cafe.go @@ -2,10 +2,11 @@ package channelserver import ( "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/mhfcourse" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" ps "erupe-ce/utils/pascalstring" "fmt" @@ -18,25 +19,33 @@ import ( func handleMsgMhfAcquireCafeItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireCafeItem) var netcafePoints uint32 - err := s.server.db.QueryRow("UPDATE characters SET netcafe_points = netcafe_points - $1 WHERE id = $2 RETURNING netcafe_points", pkt.PointCost, s.charID).Scan(&netcafePoints) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get netcafe points from db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("UPDATE characters SET netcafe_points = netcafe_points - $1 WHERE id = $2 RETURNING netcafe_points", pkt.PointCost, s.CharID).Scan(&netcafePoints) + if err != nil { + s.Logger.Error("Failed to get netcafe points from db", zap.Error(err)) } resp := byteframe.NewByteFrame() resp.WriteUint32(netcafePoints) - doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfUpdateCafepoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateCafepoint) var netcafePoints uint32 - err := s.server.db.QueryRow("SELECT COALESCE(netcafe_points, 0) FROM characters WHERE id = $1", s.charID).Scan(&netcafePoints) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get netcate points from db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT COALESCE(netcafe_points, 0) FROM characters WHERE id = $1", s.CharID).Scan(&netcafePoints) + if err != nil { + s.Logger.Error("Failed to get netcate points from db", zap.Error(err)) } resp := byteframe.NewByteFrame() resp.WriteUint32(netcafePoints) - doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) { @@ -49,9 +58,13 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) { // get time after which daily claiming would be valid from db var dailyTime time.Time - err := s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get daily_time savedata from db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.CharID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime) + if err != nil { + s.Logger.Error("Failed to get daily_time savedata from db", zap.Error(err)) } var bondBonus, bonusQuests, dailyQuests uint32 @@ -59,9 +72,9 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) { if midday.After(dailyTime) { addPointNetcafe(s, 5) bondBonus = 5 // Bond point bonus quests - bonusQuests = s.server.erupeConfig.GameplayOptions.BonusQuestAllowance - dailyQuests = s.server.erupeConfig.GameplayOptions.DailyQuestAllowance - s.server.db.Exec("UPDATE characters SET daily_time=$1, bonus_quests = $2, daily_quests = $3 WHERE id=$4", midday, bonusQuests, dailyQuests, s.charID) + bonusQuests = config.GetConfig().GameplayOptions.BonusQuestAllowance + dailyQuests = config.GetConfig().GameplayOptions.DailyQuestAllowance + database.Exec("UPDATE characters SET daily_time=$1, bonus_quests = $2, daily_quests = $3 WHERE id=$4", midday, bonusQuests, dailyQuests, s.CharID) bf.WriteBool(true) // Success? } else { bf.WriteBool(false) @@ -69,27 +82,30 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(bondBonus) bf.WriteUint32(bonusQuests) bf.WriteUint32(dailyQuests) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetCafeDuration) bf := byteframe.NewByteFrame() - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var cafeReset time.Time - err := s.server.db.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.charID).Scan(&cafeReset) + err = database.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.CharID).Scan(&cafeReset) if err != nil { cafeReset = gametime.TimeWeekNext() - s.server.db.Exec(`UPDATE characters SET cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID) + database.Exec(`UPDATE characters SET cafe_reset=$1 WHERE id=$2`, cafeReset, s.CharID) } if gametime.TimeAdjusted().After(cafeReset) { cafeReset = gametime.TimeWeekNext() - s.server.db.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID) - s.server.db.Exec(`DELETE FROM cafe_accepted WHERE character_id=$1`, s.charID) + database.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2`, cafeReset, s.CharID) + database.Exec(`DELETE FROM cafe_accepted WHERE character_id=$1`, s.CharID) } var cafeTime uint32 - err = s.server.db.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.charID).Scan(&cafeTime) + err = database.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.CharID).Scan(&cafeTime) if err != nil { panic(err) } @@ -97,11 +113,11 @@ func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) { cafeTime = uint32(gametime.TimeAdjusted().Unix()) - uint32(s.sessionStart) + cafeTime } bf.WriteUint32(cafeTime) - if _config.ErupeConfig.ClientID >= _config.ZZ { + if config.GetConfig().ClientID >= config.ZZ { bf.WriteUint16(0) - ps.Uint16(bf, fmt.Sprintf(s.server.i18n.cafe.reset, int(cafeReset.Month()), cafeReset.Day()), true) + ps.Uint16(bf, fmt.Sprintf(s.Server.i18n.cafe.reset, int(cafeReset.Month()), cafeReset.Day()), true) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type CafeBonus struct { @@ -116,26 +132,29 @@ type CafeBonus struct { func handleMsgMhfGetCafeDurationBonusInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetCafeDurationBonusInfo) bf := byteframe.NewByteFrame() - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var count uint32 - rows, err := s.server.db.Queryx(` + rows, err := database.Queryx(` SELECT cb.id, time_req, item_type, item_id, quantity, ( SELECT count(*) FROM cafe_accepted ca WHERE cb.id = ca.cafe_id AND ca.character_id = $1 )::int::bool AS claimed - FROM cafebonus cb ORDER BY id ASC;`, s.charID) + FROM cafebonus cb ORDER BY id ASC;`, s.CharID) if err != nil { - s.logger.Error("Error getting cafebonus", zap.Error(err)) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Error getting cafebonus", zap.Error(err)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) } else { for rows.Next() { count++ cafeBonus := &CafeBonus{} err = rows.StructScan(&cafeBonus) if err != nil { - s.logger.Error("Error scanning cafebonus", zap.Error(err)) + s.Logger.Error("Error scanning cafebonus", zap.Error(err)) } bf.WriteUint32(cafeBonus.TimeReq) bf.WriteUint32(cafeBonus.ItemType) @@ -148,7 +167,7 @@ func handleMsgMhfGetCafeDurationBonusInfo(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) resp.WriteUint32(count) resp.WriteBytes(bf.Data()) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } } @@ -157,7 +176,11 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() var count uint32 bf.WriteUint32(0) - rows, err := s.server.db.Queryx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(` SELECT c.id, time_req, item_type, item_id, quantity FROM cafebonus c WHERE ( @@ -168,9 +191,9 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) { SELECT ch.cafe_time + $2 FROM characters ch WHERE ch.id = $1 - ) >= time_req`, s.charID, gametime.TimeAdjusted().Unix()-s.sessionStart) + ) >= time_req`, s.CharID, gametime.TimeAdjusted().Unix()-s.sessionStart) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } else { for rows.Next() { cafeBonus := &CafeBonus{} @@ -186,15 +209,19 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) { } bf.Seek(0, io.SeekStart) bf.WriteUint32(count) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } } func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostCafeDurationBonusReceived) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var cafeBonus CafeBonus for _, cbID := range pkt.CafeBonusID { - err := s.server.db.QueryRow(` + err := database.QueryRow(` SELECT cb.id, item_type, quantity FROM cafebonus cb WHERE cb.id=$1 `, cbID).Scan(&cafeBonus.ID, &cafeBonus.ItemType, &cafeBonus.Quantity) if err == nil { @@ -202,85 +229,101 @@ func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket addPointNetcafe(s, int(cafeBonus.Quantity)) } } - s.server.db.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", cbID, s.charID) + database.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", cbID, s.CharID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func addPointNetcafe(s *Session, p int) error { var points int - err := s.server.db.QueryRow("SELECT netcafe_points FROM characters WHERE id = $1", s.charID).Scan(&points) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT netcafe_points FROM characters WHERE id = $1", s.CharID).Scan(&points) if err != nil { return err } - if points+p > s.server.erupeConfig.GameplayOptions.MaximumNP { - points = s.server.erupeConfig.GameplayOptions.MaximumNP + if points+p > config.GetConfig().GameplayOptions.MaximumNP { + points = config.GetConfig().GameplayOptions.MaximumNP } else { points += p } - s.server.db.Exec("UPDATE characters SET netcafe_points=$1 WHERE id=$2", points, s.charID) + database.Exec("UPDATE characters SET netcafe_points=$1 WHERE id=$2", points, s.CharID) return nil } func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStartBoostTime) bf := byteframe.NewByteFrame() - boostLimit := gametime.TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.BoostTimeDuration) * time.Second) - if s.server.erupeConfig.GameplayOptions.DisableBoostTime { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + boostLimit := gametime.TimeAdjusted().Add(time.Duration(config.GetConfig().GameplayOptions.BoostTimeDuration) * time.Second) + if config.GetConfig().GameplayOptions.DisableBoostTime { bf.WriteUint32(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) return } - s.server.db.Exec("UPDATE characters SET boost_time=$1 WHERE id=$2", boostLimit, s.charID) + database.Exec("UPDATE characters SET boost_time=$1 WHERE id=$2", boostLimit, s.CharID) bf.WriteUint32(uint32(boostLimit.Unix())) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetBoostTime(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetBoostTime) - doAckBufSucceed(s, pkt.AckHandle, []byte{}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{}) } func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit) bf := byteframe.NewByteFrame() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var boostLimit time.Time - err := s.server.db.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.charID).Scan(&boostLimit) + err = database.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.CharID).Scan(&boostLimit) if err != nil { bf.WriteUint32(0) } else { bf.WriteUint32(uint32(boostLimit.Unix())) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetBoostRight) var boostLimit time.Time - err := s.server.db.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.charID).Scan(&boostLimit) + database, err := db.GetDB() if err != nil { - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.CharID).Scan(&boostLimit) + if err != nil { + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } if boostLimit.After(gametime.TimeAdjusted()) { - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) } else { - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02}) } } func handleMsgMhfPostBoostTimeQuestReturn(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostBoostTimeQuestReturn) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostBoostTime) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfPostBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostBoostTimeLimit) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_campaign.go b/server/channelserver/handlers_campaign.go index 26b4788a5..7f65ca316 100644 --- a/server/channelserver/handlers_campaign.go +++ b/server/channelserver/handlers_campaign.go @@ -1,7 +1,7 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" ps "erupe-ce/utils/pascalstring" @@ -68,7 +68,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt16(event.MaxHR) bf.WriteInt16(event.MinSR) bf.WriteInt16(event.MaxSR) - if _config.ErupeConfig.ClientID >= _config.G3 { + if config.GetConfig().ClientID >= config.G3 { bf.WriteInt16(event.MinGR) bf.WriteInt16(event.MaxGR) } @@ -129,7 +129,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(link.CategoryID) bf.WriteUint32(link.CampaignID) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { @@ -137,14 +137,14 @@ func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() bf.WriteUint16(1) bf.WriteUint16(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfApplyCampaign) bf := byteframe.NewByteFrame() bf.WriteUint32(1) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) { @@ -167,10 +167,10 @@ func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(item.Unk4) bf.WriteUint32(item.Unk5) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireItem) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_caravan.go b/server/channelserver/handlers_caravan.go index e5eca75d7..29ed930fa 100644 --- a/server/channelserver/handlers_caravan.go +++ b/server/channelserver/handlers_caravan.go @@ -67,7 +67,7 @@ func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} @@ -75,12 +75,12 @@ func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetTinyBin(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetTinyBin) // requested after conquest quests - doAckBufSucceed(s, pkt.AckHandle, []byte{}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{}) } func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTinyBin) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) { @@ -92,7 +92,7 @@ func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(0) bf.WriteInt32(0) */ - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) { @@ -108,7 +108,7 @@ func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(1) bf.WriteBytes(stringsupport.PaddedString("Test", 14, true)) */ - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) { @@ -119,5 +119,5 @@ func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(0) bf.WriteInt32(0) */ - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 07643f787..ac4839eab 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -3,10 +3,11 @@ package channelserver import ( "crypto/rand" "encoding/hex" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/binpacket" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/logger" "erupe-ce/utils/mhfcid" "erupe-ce/utils/mhfcourse" @@ -43,17 +44,17 @@ const ( ) var ( - commands map[string]_config.Command + commands map[string]config.Command once sync.Once // Ensures that initialization happens only once commandsMu sync.Mutex // Mutex to ensure thread safety for commands map ) -func (server *Server) initCommands() { +func (server *ChannelServer) initCommands() { once.Do(func() { - commands = make(map[string]_config.Command) + commands = make(map[string]config.Command) commandLogger := logger.Get().Named("command") - cmds := _config.ErupeConfig.Commands + cmds := config.GetConfig().Commands for _, cmd := range cmds { commands[cmd.Name] = cmd if cmd.Enabled { @@ -65,8 +66,8 @@ func (server *Server) initCommands() { }) } -func sendDisabledCommandMessage(s *Session, cmd _config.Command) { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.disabled, cmd.Name)) +func sendDisabledCommandMessage(s *Session, cmd config.Command) { + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.disabled, cmd.Name)) } func sendServerChatMessage(s *Session, message string) { @@ -92,7 +93,11 @@ func sendServerChatMessage(s *Session, message string) { } func parseChatCommand(s *Session, command string) { - args := strings.Split(command[len(s.server.erupeConfig.CommandPrefix):], " ") + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + args := strings.Split(command[len(config.GetConfig().CommandPrefix):], " ") switch args[0] { case commands["Ban"].Prefix: if s.isOp() { @@ -118,7 +123,7 @@ func parseChatCommand(s *Session, command string) { expiry = time.Now().Add(time.Duration(length) * time.Hour * 24 * 365) } } else { - sendServerChatMessage(s, s.server.i18n.commands.ban.error) + sendServerChatMessage(s, s.Server.i18n.commands.ban.error) return } } @@ -126,39 +131,39 @@ func parseChatCommand(s *Session, command string) { if cid > 0 { var uid uint32 var uname string - err := s.server.db.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname) + err := database.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname) if err == nil { if expiry.IsZero() { - s.server.db.Exec(`INSERT INTO bans VALUES ($1) + database.Exec(`INSERT INTO bans VALUES ($1) ON CONFLICT (user_id) DO UPDATE SET expires=NULL`, uid) - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.ban.success, uname)) } else { - s.server.db.Exec(`INSERT INTO bans VALUES ($1, $2) + database.Exec(`INSERT INTO bans VALUES ($1, $2) ON CONFLICT (user_id) DO UPDATE SET expires=$2`, uid, expiry) - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.server.i18n.commands.ban.length, expiry.Format(time.DateTime))) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.Server.i18n.commands.ban.length, expiry.Format(time.DateTime))) } - s.server.DisconnectUser(uid) + s.Server.DisconnectUser(uid) } else { - sendServerChatMessage(s, s.server.i18n.commands.ban.noUser) + sendServerChatMessage(s, s.Server.i18n.commands.ban.noUser) } } else { - sendServerChatMessage(s, s.server.i18n.commands.ban.invalid) + sendServerChatMessage(s, s.Server.i18n.commands.ban.invalid) } } else { - sendServerChatMessage(s, s.server.i18n.commands.ban.error) + sendServerChatMessage(s, s.Server.i18n.commands.ban.error) } } else { - sendServerChatMessage(s, s.server.i18n.commands.noOp) + sendServerChatMessage(s, s.Server.i18n.commands.noOp) } case commands["Timer"].Prefix: if commands["Timer"].Enabled || s.isOp() { var state bool - s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&state) - s.server.db.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.charID) + database.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&state) + database.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.CharID) if state { - sendServerChatMessage(s, s.server.i18n.commands.timer.disabled) + sendServerChatMessage(s, s.Server.i18n.commands.timer.disabled) } else { - sendServerChatMessage(s, s.server.i18n.commands.timer.enabled) + sendServerChatMessage(s, s.Server.i18n.commands.timer.enabled) } } else { sendDisabledCommandMessage(s, commands["Timer"]) @@ -167,56 +172,56 @@ func parseChatCommand(s *Session, command string) { if commands["PSN"].Enabled || s.isOp() { if len(args) > 1 { var exists int - s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists) + database.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists) if exists == 0 { - _, err := s.server.db.Exec(`UPDATE users u SET psn_id=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, args[1], s.charID) + _, err := database.Exec(`UPDATE users u SET psn_id=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, args[1], s.CharID) if err == nil { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.psn.success, args[1])) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.psn.success, args[1])) } } else { - sendServerChatMessage(s, s.server.i18n.commands.psn.exists) + sendServerChatMessage(s, s.Server.i18n.commands.psn.exists) } } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.psn.error, commands["PSN"].Prefix)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.psn.error, commands["PSN"].Prefix)) } } else { sendDisabledCommandMessage(s, commands["PSN"]) } case commands["Reload"].Prefix: if commands["Reload"].Enabled || s.isOp() { - sendServerChatMessage(s, s.server.i18n.commands.reload) + sendServerChatMessage(s, s.Server.i18n.commands.reload) var temp mhfpacket.MHFPacket for _, object := range s.stage.objects { - if object.ownerCharID == s.charID { + if object.ownerCharID == s.CharID { continue } temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id} s.QueueSendMHF(temp) } - for _, session := range s.server.sessions { + for _, session := range s.Server.sessions { if s == session { continue } - temp = &mhfpacket.MsgSysDeleteUser{CharID: session.charID} + temp = &mhfpacket.MsgSysDeleteUser{CharID: session.CharID} s.QueueSendMHF(temp) } time.Sleep(500 * time.Millisecond) - for _, session := range s.server.sessions { + for _, session := range s.Server.sessions { if s == session { continue } - temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} + temp = &mhfpacket.MsgSysInsertUser{CharID: session.CharID} s.QueueSendMHF(temp) for i := 0; i < 3; i++ { temp = &mhfpacket.MsgSysNotifyUserBinary{ - CharID: session.charID, + CharID: session.CharID, BinaryType: uint8(i + 1), } s.QueueSendMHF(temp) } } for _, obj := range s.stage.objects { - if obj.ownerCharID == s.charID { + if obj.ownerCharID == s.CharID { continue } temp = &mhfpacket.MsgSysDuplicateObject{ @@ -234,20 +239,20 @@ func parseChatCommand(s *Session, command string) { } case commands["KeyQuest"].Prefix: if commands["KeyQuest"].Enabled || s.isOp() { - if s.server.erupeConfig.ClientID < _config.G10 { - sendServerChatMessage(s, s.server.i18n.commands.kqf.version) + if config.GetConfig().ClientID < config.G10 { + sendServerChatMessage(s, s.Server.i18n.commands.kqf.version) } else { if len(args) > 1 { if args[1] == "get" { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.kqf.get, s.kqf)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.kqf.get, s.kqf)) } else if args[1] == "set" { if len(args) > 2 && len(args[2]) == 16 { hexd, _ := hex.DecodeString(args[2]) s.kqf = hexd s.kqfOverride = true - sendServerChatMessage(s, s.server.i18n.commands.kqf.set.success) + sendServerChatMessage(s, s.Server.i18n.commands.kqf.set.success) } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.kqf.set.error, commands["KeyQuest"].Prefix)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.kqf.set.error, commands["KeyQuest"].Prefix)) } } } @@ -259,14 +264,14 @@ func parseChatCommand(s *Session, command string) { if commands["Rights"].Enabled || s.isOp() { if len(args) > 1 { v, _ := strconv.Atoi(args[1]) - _, err := s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", v, s.charID) + _, err := database.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", v, s.CharID) if err == nil { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.rights.success, v)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.rights.success, v)) } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.rights.error, commands["Rights"].Prefix)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.rights.error, commands["Rights"].Prefix)) } } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.rights.error, commands["Rights"].Prefix)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.rights.error, commands["Rights"].Prefix)) } } else { sendDisabledCommandMessage(s, commands["Rights"]) @@ -277,7 +282,7 @@ func parseChatCommand(s *Session, command string) { for _, course := range mhfcourse.Courses() { for _, alias := range course.Aliases() { if strings.ToLower(args[1]) == strings.ToLower(alias) { - if slices.Contains(s.server.erupeConfig.Courses, _config.Course{Name: course.Aliases()[0], Enabled: true}) { + if slices.Contains(config.GetConfig().Courses, config.Course{Name: course.Aliases()[0], Enabled: true}) { var delta, rightsInt uint32 if mhfcourse.CourseExists(course.ID, s.courses) { ei := slices.IndexFunc(s.courses, func(c mhfcourse.Course) bool { @@ -290,26 +295,26 @@ func parseChatCommand(s *Session, command string) { }) if ei != -1 { delta = uint32(-1 * math.Pow(2, float64(course.ID))) - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.disabled, course.Aliases()[0])) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.disabled, course.Aliases()[0])) } } else { delta = uint32(math.Pow(2, float64(course.ID))) - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.enabled, course.Aliases()[0])) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.enabled, course.Aliases()[0])) } - err := s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&rightsInt) + err := database.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.CharID).Scan(&rightsInt) if err == nil { - s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", rightsInt+delta, s.charID) + database.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", rightsInt+delta, s.CharID) } updateRights(s) } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.locked, course.Aliases()[0])) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.locked, course.Aliases()[0])) } return } } } } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.error, commands["Course"].Prefix)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.error, commands["Course"].Prefix)) } } else { sendDisabledCommandMessage(s, commands["Course"]) @@ -317,50 +322,50 @@ func parseChatCommand(s *Session, command string) { case commands["Raviente"].Prefix: if commands["Raviente"].Enabled || s.isOp() { if len(args) > 1 { - if s.server.getRaviSemaphore() != nil { + if s.Server.getRaviSemaphore() != nil { switch args[1] { case "start": - if s.server.raviente.register[1] == 0 { - s.server.raviente.register[1] = s.server.raviente.register[3] - sendServerChatMessage(s, s.server.i18n.commands.ravi.start.success) + if s.Server.raviente.register[1] == 0 { + s.Server.raviente.register[1] = s.Server.raviente.register[3] + sendServerChatMessage(s, s.Server.i18n.commands.ravi.start.success) s.notifyRavi() } else { - sendServerChatMessage(s, s.server.i18n.commands.ravi.start.error) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.start.error) } case "cm", "check", "checkmultiplier", "multiplier": - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ravi.multiplier, s.server.GetRaviMultiplier())) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.ravi.multiplier, s.Server.GetRaviMultiplier())) case "sr", "sendres", "resurrection", "ss", "sendsed", "rs", "reqsed": - if s.server.erupeConfig.ClientID == _config.ZZ { + if config.GetConfig().ClientID == config.ZZ { switch args[1] { case "sr", "sendres", "resurrection": - if s.server.raviente.state[28] > 0 { - sendServerChatMessage(s, s.server.i18n.commands.ravi.res.success) - s.server.raviente.state[28] = 0 + if s.Server.raviente.state[28] > 0 { + sendServerChatMessage(s, s.Server.i18n.commands.ravi.res.success) + s.Server.raviente.state[28] = 0 } else { - sendServerChatMessage(s, s.server.i18n.commands.ravi.res.error) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.res.error) } case "ss", "sendsed": - sendServerChatMessage(s, s.server.i18n.commands.ravi.sed.success) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.sed.success) // Total BerRavi HP - HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] - s.server.raviente.support[1] = HP + HP := s.Server.raviente.state[0] + s.Server.raviente.state[1] + s.Server.raviente.state[2] + s.Server.raviente.state[3] + s.Server.raviente.state[4] + s.Server.raviente.support[1] = HP case "rs", "reqsed": - sendServerChatMessage(s, s.server.i18n.commands.ravi.request) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.request) // Total BerRavi HP - HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4] - s.server.raviente.support[1] = HP + 1 + HP := s.Server.raviente.state[0] + s.Server.raviente.state[1] + s.Server.raviente.state[2] + s.Server.raviente.state[3] + s.Server.raviente.state[4] + s.Server.raviente.support[1] = HP + 1 } } else { - sendServerChatMessage(s, s.server.i18n.commands.ravi.version) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.version) } default: - sendServerChatMessage(s, s.server.i18n.commands.ravi.error) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.error) } } else { - sendServerChatMessage(s, s.server.i18n.commands.ravi.noPlayers) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.noPlayers) } } else { - sendServerChatMessage(s, s.server.i18n.commands.ravi.error) + sendServerChatMessage(s, s.Server.i18n.commands.ravi.error) } } else { sendDisabledCommandMessage(s, commands["Raviente"]) @@ -377,13 +382,13 @@ func parseChatCommand(s *Session, command string) { payload.WriteInt16(int16(y)) // Y payloadBytes := payload.Data() s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{ - CharID: s.charID, + CharID: s.CharID, MessageType: BinaryMessageTypeState, RawDataPayload: payloadBytes, }) - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.teleport.success, x, y)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.teleport.success, x, y)) } else { - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.teleport.error, commands["Teleport"].Prefix)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.teleport.error, commands["Teleport"].Prefix)) } } else { sendDisabledCommandMessage(s, commands["Teleport"]) @@ -391,14 +396,14 @@ func parseChatCommand(s *Session, command string) { case commands["Discord"].Prefix: if commands["Discord"].Enabled || s.isOp() { var _token string - err := s.server.db.QueryRow(`SELECT discord_token FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&_token) + err := database.QueryRow(`SELECT discord_token FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&_token) if err != nil { randToken := make([]byte, 4) rand.Read(randToken) _token = fmt.Sprintf("%x-%x", randToken[:2], randToken[2:]) - s.server.db.Exec(`UPDATE users u SET discord_token = $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, _token, s.charID) + database.Exec(`UPDATE users u SET discord_token = $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, _token, s.CharID) } - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.discord.success, _token)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.discord.success, _token)) } else { sendDisabledCommandMessage(s, commands["Discord"]) } @@ -406,7 +411,7 @@ func parseChatCommand(s *Session, command string) { if commands["Help"].Enabled || s.isOp() { for _, command := range commands { if command.Enabled || s.isOp() { - sendServerChatMessage(s, fmt.Sprintf("%s%s: %s", s.server.erupeConfig.CommandPrefix, command.Prefix, command.Description)) + sendServerChatMessage(s, fmt.Sprintf("%s%s: %s", config.GetConfig().CommandPrefix, command.Prefix, command.Description)) } } } else { @@ -418,21 +423,24 @@ func parseChatCommand(s *Session, command string) { func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCastBinary) tmp := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x03 && len(pkt.RawDataPayload) == 0x10 { if tmp.ReadUint16() == 0x0002 && tmp.ReadUint8() == 0x18 { var timer bool - s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&timer) + database.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&timer) if timer { _ = tmp.ReadBytes(9) tmp.SetLE() frame := tmp.ReadUint32() - sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.timer, frame/30/60/60, frame/30/60, frame/30%60, int(math.Round(float64(frame%30*100)/3)), frame)) + sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.timer, frame/30/60/60, frame/30/60, frame/30%60, int(math.Round(float64(frame%30*100)/3)), frame)) } } } - if s.server.erupeConfig.DebugOptions.QuestTools { + if config.GetConfig().DebugOptions.QuestTools { if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x02 && len(pkt.RawDataPayload) > 32 { // This is only correct most of the time tmp.ReadBytes(20) @@ -440,7 +448,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { x := tmp.ReadFloat32() y := tmp.ReadFloat32() z := tmp.ReadFloat32() - s.logger.Debug("Coord", zap.Float32s("XYZ", []float32{x, y, z})) + s.Logger.Debug("Coord", zap.Float32s("XYZ", []float32{x, y, z})) } } @@ -463,7 +471,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { msgBinTargeted = &binpacket.MsgBinTargeted{} err := msgBinTargeted.Parse(tmp) if err != nil { - s.logger.Warn("Failed to parse targeted cast binary") + s.Logger.Warn("Failed to parse targeted cast binary") return } realPayload = msgBinTargeted.RawDataPayload @@ -485,19 +493,19 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { bf.SetLE() chatMessage := &binpacket.MsgBinChat{} chatMessage.Parse(bf) - if strings.HasPrefix(chatMessage.Message, s.server.erupeConfig.CommandPrefix) { + if strings.HasPrefix(chatMessage.Message, config.GetConfig().CommandPrefix) { parseChatCommand(s, chatMessage.Message) return } if (pkt.BroadcastType == BroadcastTypeStage && s.stage.id == "sl1Ns200p0a0u0") || pkt.BroadcastType == BroadcastTypeWorld { - s.server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message) + s.Server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message) } } } // Make the response to forward to the other client(s). resp := &mhfpacket.MsgSysCastedBinary{ - CharID: s.charID, + CharID: s.CharID, BroadcastType: pkt.BroadcastType, // (The client never uses Type0 upon receiving) MessageType: pkt.MessageType, RawDataPayload: realPayload, @@ -506,7 +514,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { // Send to the proper recipients. switch pkt.BroadcastType { case BroadcastTypeWorld: - s.server.WorldcastMHF(resp, s, nil) + s.Server.WorldcastMHF(resp, s, nil) case BroadcastTypeStage: if returnToSender { s.stage.BroadcastMHF(resp, nil) @@ -515,16 +523,16 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { } case BroadcastTypeServer: if pkt.MessageType == 1 { - raviSema := s.server.getRaviSemaphore() + raviSema := s.Server.getRaviSemaphore() if raviSema != nil { raviSema.BroadcastMHF(resp, s) } } else { - s.server.BroadcastMHF(resp, s) + s.Server.BroadcastMHF(resp, s) } case BroadcastTypeTargeted: for _, targetID := range (*msgBinTargeted).TargetCharIDs { - char := s.server.FindSessionByCharID(targetID) + char := s.Server.FindSessionByCharID(targetID) if char != nil { char.QueueSendMHF(resp) diff --git a/server/channelserver/handlers_character.go b/server/channelserver/handlers_character.go index a8823c2ca..75d2db7c3 100644 --- a/server/channelserver/handlers_character.go +++ b/server/channelserver/handlers_character.go @@ -3,9 +3,11 @@ package channelserver import ( "encoding/binary" "errors" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/utils/bfutil" + "erupe-ce/utils/db" "erupe-ce/utils/stringsupport" + "fmt" "erupe-ce/network/mhfpacket" "erupe-ce/server/channelserver/compression/nullcomp" @@ -58,8 +60,8 @@ type CharacterSaveData struct { func getPointers() map[SavePointer]int { pointers := map[SavePointer]int{pGender: 81, lBookshelfData: 5576} - switch _config.ErupeConfig.ClientID { - case _config.ZZ: + switch config.GetConfig().ClientID { + case config.ZZ: pointers[pWeaponID] = 128522 pointers[pWeaponType] = 128789 pointers[pHouseTier] = 129900 @@ -72,9 +74,9 @@ func getPointers() map[SavePointer]int { pointers[pGardenData] = 142424 pointers[pRP] = 142614 pointers[pKQF] = 146720 - case _config.Z2, _config.Z1, _config.G101, _config.G10, _config.G91, _config.G9, _config.G81, _config.G8, - _config.G7, _config.G61, _config.G6, _config.G52, _config.G51, _config.G5, _config.GG, _config.G32, _config.G31, - _config.G3, _config.G2, _config.G1: + case config.Z2, config.Z1, config.G101, config.G10, config.G91, config.G9, config.G81, config.G8, + config.G7, config.G61, config.G6, config.G52, config.G51, config.G5, config.GG, config.G32, config.G31, + config.G3, config.G2, config.G1: pointers[pWeaponID] = 92522 pointers[pWeaponType] = 92789 pointers[pHouseTier] = 93900 @@ -87,7 +89,7 @@ func getPointers() map[SavePointer]int { pointers[pGardenData] = 106424 pointers[pRP] = 106614 pointers[pKQF] = 110720 - case _config.F5, _config.F4: + case config.F5, config.F4: pointers[pWeaponID] = 60522 pointers[pWeaponType] = 60789 pointers[pHouseTier] = 61900 @@ -98,7 +100,7 @@ func getPointers() map[SavePointer]int { pointers[pGalleryData] = 72064 pointers[pGardenData] = 74424 pointers[pRP] = 74614 - case _config.S6: + case config.S6: pointers[pWeaponID] = 12522 pointers[pWeaponType] = 12789 pointers[pHouseTier] = 13900 @@ -110,24 +112,28 @@ func getPointers() map[SavePointer]int { pointers[pGardenData] = 26424 pointers[pRP] = 26614 } - if _config.ErupeConfig.ClientID == _config.G5 { + if config.GetConfig().ClientID == config.G5 { pointers[lBookshelfData] = 5548 - } else if _config.ErupeConfig.ClientID <= _config.GG { + } else if config.GetConfig().ClientID <= config.GG { pointers[lBookshelfData] = 4520 } return pointers } func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) { - result, err := s.server.db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get savedata", zap.Error(err), zap.Uint32("charID", charID)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + result, err := database.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID) + if err != nil { + s.Logger.Error("Failed to get savedata", zap.Error(err), zap.Uint32("charID", charID)) return nil, err } defer result.Close() if !result.Next() { err = errors.New("no savedata found") - s.logger.Error("No savedata found", zap.Uint32("charID", charID)) + s.Logger.Error("No savedata found", zap.Uint32("charID", charID)) return nil, err } @@ -136,7 +142,7 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) } err = result.Scan(&saveData.CharID, &saveData.compSave, &saveData.IsNewCharacter, &saveData.Name) if err != nil { - s.logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID)) + s.Logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID)) return nil, err } @@ -146,7 +152,7 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) err = saveData.Decompress() if err != nil { - s.logger.Error("Failed to decompress savedata", zap.Error(err)) + s.Logger.Error("Failed to decompress savedata", zap.Error(err)) return nil, err } @@ -156,6 +162,10 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) } func (save *CharacterSaveData) Save(s *Session) { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if !s.kqfOverride { s.kqf = save.KQF } else { @@ -164,10 +174,10 @@ func (save *CharacterSaveData) Save(s *Session) { save.updateSaveDataWithStruct() - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { err := save.Compress() if err != nil { - s.logger.Error("Failed to compress savedata", zap.Error(err)) + s.Logger.Error("Failed to compress savedata", zap.Error(err)) return } } else { @@ -175,14 +185,14 @@ func (save *CharacterSaveData) Save(s *Session) { save.compSave = save.decompSave } - _, err := s.server.db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hr=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7 + _, err = database.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hr=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7 `, save.compSave, save.HR, save.GR, save.Gender, save.WeaponType, save.WeaponID, save.CharID) if err != nil { - s.logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID)) + s.Logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID)) } - s.server.db.Exec(`UPDATE user_binary SET house_tier=$1, house_data=$2, bookshelf=$3, gallery=$4, tore=$5, garden=$6 WHERE id=$7 - `, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.charID) + database.Exec(`UPDATE user_binary SET house_tier=$1, house_data=$2, bookshelf=$3, gallery=$4, tore=$5, garden=$6 WHERE id=$7 + `, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.CharID) } func (save *CharacterSaveData) Compress() error { @@ -207,10 +217,10 @@ func (save *CharacterSaveData) Decompress() error { func (save *CharacterSaveData) updateSaveDataWithStruct() { rpBytes := make([]byte, 2) binary.LittleEndian.PutUint16(rpBytes, save.RP) - if _config.ErupeConfig.ClientID >= _config.F4 { + if config.GetConfig().ClientID >= config.F4 { copy(save.decompSave[save.Pointers[pRP]:save.Pointers[pRP]+2], rpBytes) } - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+8], save.KQF) } } @@ -224,7 +234,7 @@ func (save *CharacterSaveData) updateStructWithSaveData() { save.Gender = false } if !save.IsNewCharacter { - if _config.ErupeConfig.ClientID >= _config.S6 { + if config.GetConfig().ClientID >= config.S6 { save.RP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pRP] : save.Pointers[pRP]+2]) save.HouseTier = save.decompSave[save.Pointers[pHouseTier] : save.Pointers[pHouseTier]+5] save.HouseData = save.decompSave[save.Pointers[pHouseData] : save.Pointers[pHouseData]+195] @@ -235,12 +245,12 @@ func (save *CharacterSaveData) updateStructWithSaveData() { save.WeaponType = save.decompSave[save.Pointers[pWeaponType]] save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2]) save.HR = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHR] : save.Pointers[pHR]+2]) - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { if save.HR == uint16(999) { save.GR = grpToGR(int(binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pGRP] : save.Pointers[pGRP]+4]))) } } - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { save.KQF = save.decompSave[save.Pointers[pKQF] : save.Pointers[pKQF]+8] } } @@ -250,5 +260,5 @@ func (save *CharacterSaveData) updateStructWithSaveData() { func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSexChanger) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_clients.go b/server/channelserver/handlers_clients.go index 162ad9116..df5404111 100644 --- a/server/channelserver/handlers_clients.go +++ b/server/channelserver/handlers_clients.go @@ -3,7 +3,9 @@ package channelserver import ( "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/stringsupport" + "fmt" "go.uber.org/zap" ) @@ -11,15 +13,15 @@ import ( func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysEnumerateClient) - s.server.stagesLock.RLock() - stage, ok := s.server.stages[pkt.StageID] + s.Server.stagesLock.RLock() + stage, ok := s.Server.stages[pkt.StageID] if !ok { - s.server.stagesLock.RUnlock() - s.logger.Warn("Can't enumerate clients for stage that doesn't exist!", zap.String("stageID", pkt.StageID)) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + s.Server.stagesLock.RUnlock() + s.Logger.Warn("Can't enumerate clients for stage that doesn't exist!", zap.String("stageID", pkt.StageID)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } - s.server.stagesLock.RUnlock() + s.Server.stagesLock.RUnlock() // Read-lock the stage and make the response with all of the charID's in the stage. resp := byteframe.NewByteFrame() @@ -52,23 +54,26 @@ func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) { } stage.RUnlock() - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) - s.logger.Debug("MsgSysEnumerateClient Done!") + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) + s.Logger.Debug("MsgSysEnumerateClient Done!") } func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfListMember) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var csv string var count uint32 resp := byteframe.NewByteFrame() resp.WriteUint32(0) // Blacklist count - err := s.server.db.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.charID).Scan(&csv) + err = database.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.CharID).Scan(&csv) if err == nil { cids := stringsupport.CSVElems(csv) for _, cid := range cids { var name string - err = s.server.db.QueryRow("SELECT name FROM characters WHERE id=$1", cid).Scan(&name) + err = database.QueryRow("SELECT name FROM characters WHERE id=$1", cid).Scan(&name) if err != nil { continue } @@ -80,36 +85,40 @@ func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) { } resp.Seek(0, 0) resp.WriteUint32(count) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOprMember) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var csv string for _, cid := range pkt.CharIDs { if pkt.Blacklist { - err := s.server.db.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.charID).Scan(&csv) + err := database.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.CharID).Scan(&csv) if err == nil { if pkt.Operation { csv = stringsupport.CSVRemove(csv, int(cid)) } else { csv = stringsupport.CSVAdd(csv, int(cid)) } - s.server.db.Exec("UPDATE characters SET blocked=$1 WHERE id=$2", csv, s.charID) + database.Exec("UPDATE characters SET blocked=$1 WHERE id=$2", csv, s.CharID) } } else { // Friendlist - err := s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&csv) + err := database.QueryRow("SELECT friends FROM characters WHERE id=$1", s.CharID).Scan(&csv) if err == nil { if pkt.Operation { csv = stringsupport.CSVRemove(csv, int(cid)) } else { csv = stringsupport.CSVAdd(csv, int(cid)) } - s.server.db.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.charID) + database.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.CharID) } } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfShutClient(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_data.go b/server/channelserver/handlers_data.go index d582d1b7c..3b69a2b1c 100644 --- a/server/channelserver/handlers_data.go +++ b/server/channelserver/handlers_data.go @@ -1,7 +1,8 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/mhfmon" "erupe-ce/utils/stringsupport" @@ -21,9 +22,13 @@ import ( func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSavedata) - characterSaveData, err := GetCharacterSaveData(s, s.charID) + database, err := db.GetDB() if err != nil { - s.logger.Error("failed to retrieve character save data from db", zap.Error(err), zap.Uint32("charID", s.charID)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + characterSaveData, err := GetCharacterSaveData(s, s.CharID) + if err != nil { + s.Logger.Error("failed to retrieve character save data from db", zap.Error(err), zap.Uint32("charID", s.CharID)) return } // Var to hold the decompressed savedata for updating the launcher response fields. @@ -32,26 +37,26 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) { // diffs themselves are also potentially compressed diff, err := nullcomp.Decompress(pkt.RawDataPayload) if err != nil { - s.logger.Error("Failed to decompress diff", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to decompress diff", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } // Perform diff. - s.logger.Info("Diffing...") + s.Logger.Info("Diffing...") characterSaveData.decompSave = deltacomp.ApplyDataDiff(diff, characterSaveData.decompSave) } else { dumpSaveData(s, pkt.RawDataPayload, "savedata") // Regular blob update. saveData, err := nullcomp.Decompress(pkt.RawDataPayload) if err != nil { - s.logger.Error("Failed to decompress savedata from packet", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to decompress savedata from packet", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } - if s.server.erupeConfig.SaveDumps.RawEnabled { + if config.GetConfig().SaveDumps.RawEnabled { dumpSaveData(s, saveData, "raw-savedata") } - s.logger.Info("Updating save with blob") + s.Logger.Info("Updating save with blob") characterSaveData.decompSave = saveData } characterSaveData.updateStructWithSaveData() @@ -61,22 +66,22 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) { s.Name = characterSaveData.Name } - if characterSaveData.Name == s.Name || _config.ErupeConfig.ClientID <= _config.S10 { + if characterSaveData.Name == s.Name || config.GetConfig().ClientID <= config.S10 { characterSaveData.Save(s) - s.logger.Info("Wrote recompressed savedata back to DB.") + s.Logger.Info("Wrote recompressed savedata back to DB.") } else { s.rawConn.Close() - s.logger.Warn("Save cancelled due to corruption.") - if s.server.erupeConfig.DeleteOnSaveCorruption { - s.server.db.Exec("UPDATE characters SET deleted=true WHERE id=$1", s.charID) + s.Logger.Warn("Save cancelled due to corruption.") + if config.GetConfig().DeleteOnSaveCorruption { + database.Exec("UPDATE characters SET deleted=true WHERE id=$1", s.CharID) } return } - _, err = s.server.db.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterSaveData.Name, s.charID) + _, err = database.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterSaveData.Name, s.CharID) if err != nil { - s.logger.Error("Failed to update character name in db", zap.Error(err)) + s.Logger.Error("Failed to update character name in db", zap.Error(err)) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func grpToGR(n int) uint16 { @@ -115,83 +120,95 @@ func grpToGR(n int) uint16 { } func dumpSaveData(s *Session, data []byte, suffix string) { - if !s.server.erupeConfig.SaveDumps.Enabled { + if !config.GetConfig().SaveDumps.Enabled { return } else { - dir := filepath.Join(s.server.erupeConfig.SaveDumps.OutputDir, fmt.Sprintf("%d", s.charID)) - path := filepath.Join(s.server.erupeConfig.SaveDumps.OutputDir, fmt.Sprintf("%d", s.charID), fmt.Sprintf("%d_%s.bin", s.charID, suffix)) + dir := filepath.Join(config.GetConfig().SaveDumps.OutputDir, fmt.Sprintf("%d", s.CharID)) + path := filepath.Join(config.GetConfig().SaveDumps.OutputDir, fmt.Sprintf("%d", s.CharID), fmt.Sprintf("%d_%s.bin", s.CharID, suffix)) _, err := os.Stat(dir) if err != nil { if os.IsNotExist(err) { err = os.MkdirAll(dir, os.ModePerm) if err != nil { - s.logger.Error("Error dumping savedata, could not create folder") + s.Logger.Error("Error dumping savedata, could not create folder") return } } else { - s.logger.Error("Error dumping savedata") + s.Logger.Error("Error dumping savedata") return } } err = os.WriteFile(path, data, 0644) if err != nil { - s.logger.Error("Error dumping savedata, could not write file", zap.Error(err)) + s.Logger.Error("Error dumping savedata, could not write file", zap.Error(err)) } } } func handleMsgMhfLoaddata(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoaddata) - if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, "save_override.bin")); err == nil { - data, _ := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "save_override.bin")) - doAckBufSucceed(s, pkt.AckHandle, data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + if _, err := os.Stat(filepath.Join(config.GetConfig().BinPath, "save_override.bin")); err == nil { + data, _ := os.ReadFile(filepath.Join(config.GetConfig().BinPath, "save_override.bin")) + DoAckBufSucceed(s, pkt.AckHandle, data) return } var data []byte - err := s.server.db.QueryRow("SELECT savedata FROM characters WHERE id = $1", s.charID).Scan(&data) + err = database.QueryRow("SELECT savedata FROM characters WHERE id = $1", s.CharID).Scan(&data) if err != nil || len(data) == 0 { - s.logger.Warn(fmt.Sprintf("Failed to load savedata (CID: %d)", s.charID), zap.Error(err)) + s.Logger.Warn(fmt.Sprintf("Failed to load savedata (CID: %d)", s.CharID), zap.Error(err)) s.rawConn.Close() // Terminate the connection return } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) decompSaveData, err := nullcomp.Decompress(data) if err != nil { - s.logger.Error("Failed to decompress savedata", zap.Error(err)) + s.Logger.Error("Failed to decompress savedata", zap.Error(err)) } bf := byteframe.NewByteFrameFromBytes(decompSaveData) bf.Seek(88, io.SeekStart) name := bf.ReadNullTerminatedBytes() - s.server.userBinaryPartsLock.Lock() - s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: 1}] = append(name, []byte{0x00}...) - s.server.userBinaryPartsLock.Unlock() + s.Server.userBinaryPartsLock.Lock() + s.Server.userBinaryParts[userBinaryPartID{charID: s.CharID, index: 1}] = append(name, []byte{0x00}...) + s.Server.userBinaryPartsLock.Unlock() s.Name = stringsupport.SJISToUTF8(name) } func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveScenarioData) - dumpSaveData(s, pkt.RawDataPayload, "scenario") - _, err := s.server.db.Exec("UPDATE characters SET scenariodata = $1 WHERE id = $2", pkt.RawDataPayload, s.charID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to update scenario data in db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + dumpSaveData(s, pkt.RawDataPayload, "scenario") + _, err = database.Exec("UPDATE characters SET scenariodata = $1 WHERE id = $2", pkt.RawDataPayload, s.CharID) + if err != nil { + s.Logger.Error("Failed to update scenario data in db", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadScenarioData) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var scenarioData []byte bf := byteframe.NewByteFrame() - err := s.server.db.QueryRow("SELECT scenariodata FROM characters WHERE id = $1", s.charID).Scan(&scenarioData) + err = database.QueryRow("SELECT scenariodata FROM characters WHERE id = $1", s.CharID).Scan(&scenarioData) if err != nil || len(scenarioData) < 10 { - s.logger.Error("Failed to load scenariodata", zap.Error(err)) + s.Logger.Error("Failed to load scenariodata", zap.Error(err)) bf.WriteBytes(make([]byte, 10)) } else { bf.WriteBytes(scenarioData) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } var paperGiftData = map[uint32][]PaperGift{ @@ -1509,7 +1526,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { } default: if pkt.Unk2 < 1000 { - s.logger.Info("PaperData request for unknown type", zap.Uint32("Unk2", pkt.Unk2)) + s.Logger.Info("PaperData request for unknown type", zap.Uint32("Unk2", pkt.Unk2)) } } @@ -1518,7 +1535,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { if ok { paperGift = paperGiftData[pkt.Unk2] } else { - s.logger.Info("PaperGift request for unknown type", zap.Uint32("Unk2", pkt.Unk2)) + s.Logger.Info("PaperGift request for unknown type", zap.Uint32("Unk2", pkt.Unk2)) } for _, gift := range paperGift { bf := byteframe.NewByteFrame() @@ -1528,7 +1545,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(gift.Unk3) data = append(data, bf) } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } else if pkt.Unk2 == 0 { bf := byteframe.NewByteFrame() bf.WriteUint16(uint16(len(paperMissions.Timetables))) @@ -1546,7 +1563,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(mdata.Reward2ID) bf.WriteUint8(mdata.Reward2Quantity) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } else { for _, pdata := range paperData { bf := byteframe.NewByteFrame() @@ -1559,7 +1576,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt16(pdata.Unk6) data = append(data, bf) } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } } diff --git a/server/channelserver/handlers_distitem.go b/server/channelserver/handlers_distitem.go index 670c968cf..7008953c3 100644 --- a/server/channelserver/handlers_distitem.go +++ b/server/channelserver/handlers_distitem.go @@ -1,10 +1,12 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" ps "erupe-ce/utils/pascalstring" + "fmt" "time" "go.uber.org/zap" @@ -32,7 +34,11 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { var itemDists []Distribution bf := byteframe.NewByteFrame() - rows, err := s.server.db.Queryx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(` SELECT d.id, event_name, description, COALESCE(rights, 0) AS rights, COALESCE(selection, false) AS selection, times_acceptable, COALESCE(min_hr, -1) AS min_hr, COALESCE(max_hr, -1) AS max_hr, COALESCE(min_sr, -1) AS min_sr, COALESCE(max_sr, -1) AS max_sr, @@ -44,7 +50,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { COALESCE(deadline, TO_TIMESTAMP(0)) AS deadline FROM distribution d WHERE character_id = $1 AND type = $2 OR character_id IS NULL AND type = $2 ORDER BY id DESC - `, s.charID, pkt.DistType) + `, s.CharID, pkt.DistType) if err == nil { var itemDist Distribution @@ -64,7 +70,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(dist.Rights) bf.WriteUint16(dist.TimesAcceptable) bf.WriteUint16(dist.TimesAccepted) - if _config.ErupeConfig.ClientID >= _config.G9 { + if config.GetConfig().ClientID >= config.G9 { bf.WriteUint16(0) // Unk } bf.WriteInt16(dist.MinHR) @@ -73,29 +79,29 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt16(dist.MaxSR) bf.WriteInt16(dist.MinGR) bf.WriteInt16(dist.MaxGR) - if _config.ErupeConfig.ClientID >= _config.G7 { + if config.GetConfig().ClientID >= config.G7 { bf.WriteUint8(0) // Unk } - if _config.ErupeConfig.ClientID >= _config.G6 { + if config.GetConfig().ClientID >= config.G6 { bf.WriteUint16(0) // Unk } - if _config.ErupeConfig.ClientID >= _config.G8 { + if config.GetConfig().ClientID >= config.G8 { if dist.Selection { bf.WriteUint8(2) // Selection } else { bf.WriteUint8(0) } } - if _config.ErupeConfig.ClientID >= _config.G7 { + if config.GetConfig().ClientID >= config.G7 { bf.WriteUint16(0) // Unk bf.WriteUint16(0) // Unk } - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { bf.WriteUint8(0) // Unk } ps.Uint8(bf, dist.EventName, true) k := 6 - if _config.ErupeConfig.ClientID >= _config.G8 { + if config.GetConfig().ClientID >= config.G8 { k = 13 } for i := 0; i < 6; i++ { @@ -104,7 +110,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(0) } } - if _config.ErupeConfig.ClientID >= _config.Z2 { + if config.GetConfig().ClientID >= config.Z2 { i := uint8(0) bf.WriteUint8(i) if i <= 10 { @@ -116,7 +122,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { } } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type DistributionItem struct { @@ -127,8 +133,12 @@ type DistributionItem struct { } func getDistributionItems(s *Session, i uint32) []DistributionItem { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var distItems []DistributionItem - rows, err := s.server.db.Queryx(`SELECT id, item_type, COALESCE(item_id, 0) AS item_id, COALESCE(quantity, 0) AS quantity FROM distribution_items WHERE distribution_id=$1`, i) + rows, err := database.Queryx(`SELECT id, item_type, COALESCE(item_id, 0) AS item_id, COALESCE(quantity, 0) AS quantity FROM distribution_items WHERE distribution_id=$1`, i) if err == nil { var distItem DistributionItem for rows.Next() { @@ -152,17 +162,21 @@ func handleMsgMhfApplyDistItem(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(item.ItemType) bf.WriteUint32(item.ItemID) bf.WriteUint32(item.Quantity) - if _config.ErupeConfig.ClientID >= _config.G8 { + if config.GetConfig().ClientID >= config.G8 { bf.WriteUint32(item.ID) } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireDistItem) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.DistributionID > 0 { - _, err := s.server.db.Exec(`INSERT INTO public.distributions_accepted VALUES ($1, $2)`, pkt.DistributionID, s.charID) + _, err := database.Exec(`INSERT INTO public.distributions_accepted VALUES ($1, $2)`, pkt.DistributionID, s.CharID) if err == nil { distItems := getDistributionItems(s, pkt.DistributionID) for _, item := range distItems { @@ -170,13 +184,13 @@ func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) { case 17: _ = addPointNetcafe(s, int(item.Quantity)) case 19: - s.server.db.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID) + database.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID) case 20: - s.server.db.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID) + database.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID) case 21: - s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID) + database.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID) case 23: - saveData, err := GetCharacterSaveData(s, s.charID) + saveData, err := GetCharacterSaveData(s, s.CharID) if err == nil { saveData.RP += uint16(item.Quantity) saveData.Save(s) @@ -185,20 +199,24 @@ func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) { } } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfGetDistDescription(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetDistDescription) - var desc string - err := s.server.db.QueryRow("SELECT description FROM distribution WHERE id = $1", pkt.DistributionID).Scan(&desc) + database, err := db.GetDB() if err != nil { - s.logger.Error("Error parsing item distribution description", zap.Error(err)) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var desc string + err = database.QueryRow("SELECT description FROM distribution WHERE id = $1", pkt.DistributionID).Scan(&desc) + if err != nil { + s.Logger.Error("Error parsing item distribution description", zap.Error(err)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } bf := byteframe.NewByteFrame() ps.Uint16(bf, desc, true) ps.Uint16(bf, "", false) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_diva.go b/server/channelserver/handlers_diva.go index 8fee29610..d2f3e690d 100644 --- a/server/channelserver/handlers_diva.go +++ b/server/channelserver/handlers_diva.go @@ -2,9 +2,11 @@ package channelserver import ( "encoding/hex" - _config "erupe-ce/config" + config "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/stringsupport" + "fmt" "time" "erupe-ce/network/mhfpacket" @@ -12,10 +14,18 @@ import ( ) func cleanupDiva(s *Session) { - s.server.db.Exec("DELETE FROM events WHERE event_type='diva'") + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("DELETE FROM events WHERE event_type='diva'") } func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } timestamps := make([]uint32, 6) midnight := gametime.TimeMidnight() if debug && start <= 3 { @@ -49,7 +59,7 @@ func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 { cleanupDiva(s) // Generate a new diva defense, starting midnight tomorrow start = uint32(midnight.Add(24 * time.Hour).Unix()) - s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('diva', to_timestamp($1)::timestamp without time zone)", start) + database.Exec("INSERT INTO events (event_type, start_time) VALUES ('diva', to_timestamp($1)::timestamp without time zone)", start) } timestamps[0] = start timestamps[1] = timestamps[0] + 601200 @@ -63,29 +73,32 @@ func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 { func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdSchedule) bf := byteframe.NewByteFrame() - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } id, start := uint32(0xCAFEBEEF), uint32(0) - rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'") + rows, _ := database.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'") for rows.Next() { rows.Scan(&id, &start) } var timestamps []uint32 - if s.server.erupeConfig.DebugOptions.DivaOverride >= 0 { - if s.server.erupeConfig.DebugOptions.DivaOverride == 0 { - if s.server.erupeConfig.ClientID >= _config.Z2 { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36)) + if config.GetConfig().DebugOptions.DivaOverride >= 0 { + if config.GetConfig().DebugOptions.DivaOverride == 0 { + if config.GetConfig().ClientID >= config.Z2 { + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 36)) } else { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 32)) } return } - timestamps = generateDivaTimestamps(s, uint32(s.server.erupeConfig.DebugOptions.DivaOverride), true) + timestamps = generateDivaTimestamps(s, uint32(config.GetConfig().DebugOptions.DivaOverride), true) } else { timestamps = generateDivaTimestamps(s, start, false) } - if s.server.erupeConfig.ClientID >= _config.Z2 { + if config.GetConfig().ClientID >= config.Z2 { bf.WriteUint32(id) } for i := range timestamps { @@ -97,7 +110,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(0x02) // Unk 00000010 bf.WriteUint16(0x02) // Unk 00000010 - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) { @@ -117,45 +130,45 @@ func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(uint32(udInfo.EndTime.Unix())) } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfGetKijuInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetKijuInfo) // Temporary canned response data, _ := hex.DecodeString("04965C959782CC8B468EEC00000000000000000000000000000000000000000000815C82A082E782B582DC82A982BA82CC82AB82B682E3815C0A965C959782C682CD96D282E98E7682A281420A95B782AD8ED282C997458B4382F0975E82A682E98142000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001018BAD8C8282CC8B468EEC00000000000000000000000000000000000000000000815C82AB82E582A482B082AB82CC82AB82B682E3815C0A8BAD8C8282C682CD8BAD82A290BA904681420A95B782AD8ED282CC97CD82F08CA482AC909F82DC82B78142200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003138C8B8F5782CC8B468EEC00000000000000000000000000000000000000000000815C82AF82C182B582E382A482CC82AB82B682E3815C0A8C8B8F5782C682CD8A6D8CC582BD82E9904D978A81420A8F5782DF82E982D982C782C98EEB906C82BD82BF82CC90B8905F97CD82C682C882E9814200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041189CC8CEC82CC8B468EEC00000000000000000000000000000000000000000000815C82A482BD82DC82E082E882CC82AB82B682E3815C0A89CC8CEC82C682CD89CC955082CC8CEC82E881420A8F5782DF82E982D982C782C98EEB906C82BD82BF82CC8E7882A682C682C882E9814220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSetKiju(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetKiju) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfAddUdPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAddUdPoint) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfGetUdMyPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdMyPoint) // Temporary canned response data, _ := hex.DecodeString("00040000013C000000FA000000000000000000040000007E0000003C02000000000000000000000000000000000000000000000000000002000004CC00000438000000000000000000000000000000000000000000000000000000020000026E00000230000000000000000000020000007D0000007D000000000000000000000000000000000000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetUdTotalPointInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTotalPointInfo) // Temporary canned response data, _ := hex.DecodeString("00000000000007A12000000000000F424000000000001E848000000000002DC6C000000000003D090000000000004C4B4000000000005B8D8000000000006ACFC000000000007A1200000000000089544000000000009896800000000000E4E1C00000000001312D0000000000017D78400000000001C9C3800000000002160EC00000000002625A000000000002AEA5400000000002FAF0800000000003473BC0000000000393870000000000042C1D800000000004C4B40000000000055D4A800000000005F5E10000000000008954400000000001C9C3800000000003473BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020300000000000000000000000000000000000000000000000000000000000000000000000000000000101F1420") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetUdSelectedColorInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdSelectedColorInfo) // Unk - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00}) } func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) { @@ -287,36 +300,36 @@ func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint16(mp.Points) } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfGetUdDailyPresentList(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdDailyPresentList) // Temporary canned response data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetUdNormaPresentList(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdNormaPresentList) // Temporary canned response data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfAcquireUdItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireUdItem) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfGetUdRanking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdRanking) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfGetUdMyRanking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdMyRanking) // Temporary canned response data, _ := hex.DecodeString("00000515000005150000CEB4000003CE000003CE0000CEB44D49444E494748542D414E47454C0000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } diff --git a/server/channelserver/handlers_event.go b/server/channelserver/handlers_event.go index d2a4f62e1..ac95fe668 100644 --- a/server/channelserver/handlers_event.go +++ b/server/channelserver/handlers_event.go @@ -1,9 +1,11 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/token" + "fmt" "math" "time" @@ -45,7 +47,7 @@ func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) { } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type activeFeature struct { @@ -55,7 +57,10 @@ type activeFeature struct { func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetWeeklySchedule) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var features []activeFeature times := []time.Time{ gametime.TimeMidnight().Add(-24 * time.Hour), @@ -65,12 +70,12 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { for _, t := range times { var temp activeFeature - err := s.server.db.QueryRowx(`SELECT start_time, featured FROM feature_weapon WHERE start_time=$1`, t).StructScan(&temp) + err := database.QueryRowx(`SELECT start_time, featured FROM feature_weapon WHERE start_time=$1`, t).StructScan(&temp) if err != nil || temp.StartTime.IsZero() { - weapons := token.RNG.Intn(s.server.erupeConfig.GameplayOptions.MaxFeatureWeapons-s.server.erupeConfig.GameplayOptions.MinFeatureWeapons+1) + s.server.erupeConfig.GameplayOptions.MinFeatureWeapons + weapons := token.RNG.Intn(config.GetConfig().GameplayOptions.MaxFeatureWeapons-config.GetConfig().GameplayOptions.MinFeatureWeapons+1) + config.GetConfig().GameplayOptions.MinFeatureWeapons temp = generateFeatureWeapons(weapons) temp.StartTime = t - s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures) + database.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures) } features = append(features, temp) } @@ -83,18 +88,18 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(feature.ActiveFeatures) bf.WriteUint16(0) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func generateFeatureWeapons(count int) activeFeature { _max := 14 - if _config.ErupeConfig.ClientID < _config.ZZ { + if config.GetConfig().ClientID < config.ZZ { _max = 13 } - if _config.ErupeConfig.ClientID < _config.G10 { + if config.GetConfig().ClientID < config.G10 { _max = 12 } - if _config.ErupeConfig.ClientID < _config.GG { + if config.GetConfig().ClientID < config.GG { _max = 11 } if count > _max { @@ -131,14 +136,17 @@ type loginBoost struct { func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetKeepLoginBoostStatus) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() var loginBoosts []loginBoost - rows, err := s.server.db.Queryx("SELECT week_req, expiration, reset FROM login_boost WHERE char_id=$1 ORDER BY week_req", s.charID) - if err != nil || s.server.erupeConfig.GameplayOptions.DisableLoginBoost { + rows, err := database.Queryx("SELECT week_req, expiration, reset FROM login_boost WHERE char_id=$1 ORDER BY week_req", s.CharID) + if err != nil || config.GetConfig().GameplayOptions.DisableLoginBoost { rows.Close() - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 35)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 35)) return } for rows.Next() { @@ -156,7 +164,7 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) { {WeekReq: 5, Expiration: temp}, } for _, boost := range loginBoosts { - s.server.db.Exec(`INSERT INTO login_boost VALUES ($1, $2, $3, $4)`, s.charID, boost.WeekReq, boost.Expiration, time.Time{}) + database.Exec(`INSERT INTO login_boost VALUES ($1, $2, $3, $4)`, s.CharID, boost.WeekReq, boost.Expiration, time.Time{}) } } @@ -165,7 +173,7 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) { if !boost.Reset.IsZero() && boost.Reset.Before(gametime.TimeAdjusted()) { boost.Expiration = gametime.TimeWeekStart() boost.Reset = time.Time{} - s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, boost.Expiration, boost.Reset, s.charID, boost.WeekReq) + database.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, boost.Expiration, boost.Reset, s.CharID, boost.WeekReq) } boost.WeekCount = uint8((gametime.TimeAdjusted().Unix()-boost.Expiration.Unix())/604800 + 1) @@ -191,7 +199,7 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) { } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) { @@ -208,13 +216,17 @@ func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) { expiration = gametime.TimeAdjusted().Add(240 * time.Minute) } bf.WriteUint32(uint32(expiration.Unix())) - s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, expiration, gametime.TimeWeekNext(), s.charID, pkt.BoostWeekUsed) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, expiration, gametime.TimeWeekNext(), s.CharID, pkt.BoostWeekUsed) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfSetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetRestrictionEvent) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_festa.go b/server/channelserver/handlers_festa.go index bd4f1c4c5..02b411c4a 100644 --- a/server/channelserver/handlers_festa.go +++ b/server/channelserver/handlers_festa.go @@ -1,26 +1,36 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" ps "erupe-ce/utils/pascalstring" "erupe-ce/utils/token" + "fmt" "sort" "time" ) func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveMezfesData) - s.server.db.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadMezfesData) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var data []byte - s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data) + database.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.CharID).Scan(&data) bf := byteframe.NewByteFrame() if len(data) > 0 { bf.WriteBytes(data) @@ -31,13 +41,13 @@ func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(0) bf.WriteUint32(0) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateRanking) bf := byteframe.NewByteFrame() - state := s.server.erupeConfig.DebugOptions.TournamentOverride + state := config.GetConfig().DebugOptions.TournamentOverride // Unk // Unk // Start? @@ -64,7 +74,7 @@ func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) // TS Current Time bf.WriteUint8(3) bf.WriteBytes(make([]byte, 4)) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) return } bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) // TS Current Time @@ -90,18 +100,26 @@ func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) { psUint16 desc */ - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func cleanupFesta(s *Session) { - s.server.db.Exec("DELETE FROM events WHERE event_type='festa'") - s.server.db.Exec("DELETE FROM festa_registrations") - s.server.db.Exec("DELETE FROM festa_submissions") - s.server.db.Exec("DELETE FROM festa_prizes_accepted") - s.server.db.Exec("UPDATE guild_characters SET trial_vote=NULL") + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("DELETE FROM events WHERE event_type='festa'") + database.Exec("DELETE FROM festa_registrations") + database.Exec("DELETE FROM festa_submissions") + database.Exec("DELETE FROM festa_prizes_accepted") + database.Exec("UPDATE guild_characters SET trial_vote=NULL") } func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } timestamps := make([]uint32, 5) midnight := gametime.TimeMidnight() if debug && start <= 3 { @@ -132,7 +150,7 @@ func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 { cleanupFesta(s) // Generate a new festa, starting midnight tomorrow start = uint32(midnight.Add(24 * time.Hour).Unix()) - s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start) + database.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start) } timestamps[0] = start timestamps[1] = timestamps[0] + 604800 @@ -167,32 +185,35 @@ type FestaReward struct { func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfInfoFesta) bf := byteframe.NewByteFrame() - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } id, start := uint32(0xDEADBEEF), uint32(0) - rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'") + rows, _ := database.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'") for rows.Next() { rows.Scan(&id, &start) } var timestamps []uint32 - if s.server.erupeConfig.DebugOptions.FestaOverride >= 0 { - if s.server.erupeConfig.DebugOptions.FestaOverride == 0 { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + if config.GetConfig().DebugOptions.FestaOverride >= 0 { + if config.GetConfig().DebugOptions.FestaOverride == 0 { + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } - timestamps = generateFestaTimestamps(s, uint32(s.server.erupeConfig.DebugOptions.FestaOverride), true) + timestamps = generateFestaTimestamps(s, uint32(config.GetConfig().DebugOptions.FestaOverride), true) } else { timestamps = generateFestaTimestamps(s, start, false) } if timestamps[0] > uint32(gametime.TimeAdjusted().Unix()) { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } var blueSouls, redSouls uint32 - s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls) - s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls) + database.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls) + database.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls) bf.WriteUint32(id) for _, timestamp := range timestamps { @@ -207,7 +228,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { var trials []FestaTrial var trial FestaTrial - rows, _ = s.server.db.Queryx(`SELECT ft.*, + rows, _ = database.Queryx(`SELECT ft.*, COALESCE(CASE WHEN COUNT(gc.id) FILTER (WHERE fr.team = 'blue' AND gc.trial_vote = ft.id) > COUNT(gc.id) FILTER (WHERE fr.team = 'red' AND gc.trial_vote = ft.id) @@ -236,7 +257,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(trial.Locale) bf.WriteUint16(trial.Reward) bf.WriteInt16(FestivalColorCodes[trial.Monopoly]) - if _config.ErupeConfig.ClientID >= _config.F4 { // Not in S6.0 + if config.GetConfig().ClientID >= config.F4 { // Not in S6.0 bf.WriteUint16(trial.Unk) } } @@ -279,19 +300,19 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(reward.Quantity) bf.WriteUint16(reward.ItemID) // Not confirmed to be G1 but exists in G3 - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { bf.WriteUint16(reward.Unk5) bf.WriteUint16(reward.Unk6) bf.WriteUint8(reward.Unk7) } } - if _config.ErupeConfig.ClientID <= _config.G61 { - if s.server.erupeConfig.GameplayOptions.MaximumFP > 0xFFFF { - s.server.erupeConfig.GameplayOptions.MaximumFP = 0xFFFF + if config.GetConfig().ClientID <= config.G61 { + if config.GetConfig().GameplayOptions.MaximumFP > 0xFFFF { + config.GetConfig().GameplayOptions.MaximumFP = 0xFFFF } - bf.WriteUint16(uint16(s.server.erupeConfig.GameplayOptions.MaximumFP)) + bf.WriteUint16(uint16(config.GetConfig().GameplayOptions.MaximumFP)) } else { - bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MaximumFP) + bf.WriteUint32(config.GetConfig().GameplayOptions.MaximumFP) } bf.WriteUint16(100) // Reward multiplier (%) @@ -301,7 +322,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { var guildID uint32 var guildName string var guildTeam = FestivalColorNone - s.server.db.QueryRow(` + database.QueryRow(` SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _ FROM festa_submissions fs LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id @@ -321,7 +342,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { var guildName string var guildTeam = FestivalColorNone offset := 86400 * uint32(i) - s.server.db.QueryRow(` + database.QueryRow(` SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _ FROM festa_submissions fs LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id @@ -348,27 +369,31 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(100) // Normal rate bf.WriteUint16(50) // 50% penalty - if _config.ErupeConfig.ClientID >= _config.G52 { + if config.GetConfig().ClientID >= config.G52 { ps.Uint16(bf, "", false) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } // state festa (U)ser func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStateFestaU) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, err := GetGuildInfoByCharacterId(s, s.CharID) applicant := false if guild != nil { - applicant, _ = guild.HasApplicationForCharID(s, s.charID) + applicant, _ = guild.HasApplicationForCharID(s, s.CharID) } if err != nil || guild == nil || applicant { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } var souls, exists uint32 - s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.charID).Scan(&souls) - err = s.server.db.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.charID).Scan(&exists) + database.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.CharID).Scan(&souls) + err = database.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.CharID).Scan(&exists) bf := byteframe.NewByteFrame() bf.WriteUint32(souls) if err != nil { @@ -378,16 +403,16 @@ func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) { bf.WriteBool(false) bf.WriteBool(true) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } // state festa (G)uild func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStateFestaG) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) applicant := false if guild != nil { - applicant, _ = guild.HasApplicationForCharID(s, s.charID) + applicant, _ = guild.HasApplicationForCharID(s, s.CharID) } resp := byteframe.NewByteFrame() if err != nil || guild == nil || applicant { @@ -396,7 +421,7 @@ func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) { resp.WriteInt32(-1) resp.WriteInt32(0) resp.WriteInt32(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) return } resp.WriteUint32(guild.Souls) @@ -404,19 +429,19 @@ func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) { resp.WriteInt32(1) // unk, rank? resp.WriteInt32(1) // unk resp.WriteInt32(1) // unk - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateFestaMember) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil || guild == nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } members, err := GetGuildMembers(s, guild.ID, false) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } sort.Slice(members, func(i, j int) bool { @@ -433,70 +458,94 @@ func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(0) // Unk for _, member := range validMembers { bf.WriteUint32(member.CharID) - if _config.ErupeConfig.ClientID <= _config.Z1 { + if config.GetConfig().ClientID <= config.Z1 { bf.WriteUint16(uint16(member.Souls)) bf.WriteUint16(0) } else { bf.WriteUint32(member.Souls) } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfVoteFesta) - s.server.db.Exec(`UPDATE guild_characters SET trial_vote=$1 WHERE character_id=$2`, pkt.TrialID, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE guild_characters SET trial_vote=$1 WHERE character_id=$2`, pkt.TrialID, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEntryFesta) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil || guild == nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } team := uint32(token.RNG.Intn(2)) switch team { case 0: - s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID) + database.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID) case 1: - s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID) + database.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID) } bf := byteframe.NewByteFrame() bf.WriteUint32(team) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfChargeFesta) - tx, _ := s.server.db.Begin() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + tx, _ := database.Begin() for i := range pkt.Souls { if pkt.Souls[i] == 0 { continue } - _, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i]) + _, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.CharID, pkt.GuildID, i, pkt.Souls[i]) } _ = tx.Commit() - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfAcquireFesta(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireFesta) - s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfAcquireFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireFestaPersonalPrize) - s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireFestaIntermediatePrize) - s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type Prize struct { @@ -510,7 +559,11 @@ type Prize struct { func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateFestaPersonalPrize) - rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, _ := database.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.CharID) var count uint32 prizeData := byteframe.NewByteFrame() for rows.Next() { @@ -531,12 +584,16 @@ func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) bf := byteframe.NewByteFrame() bf.WriteUint32(count) bf.WriteBytes(prizeData.Data()) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateFestaIntermediatePrize) - rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, _ := database.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.CharID) var count uint32 prizeData := byteframe.NewByteFrame() for rows.Next() { @@ -557,5 +614,5 @@ func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPack bf := byteframe.NewByteFrame() bf.WriteUint32(count) bf.WriteBytes(prizeData.Data()) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index e00f39f16..0a4f45634 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -5,7 +5,8 @@ import ( "database/sql/driver" "encoding/json" "errors" - _config "erupe-ce/config" + "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/mhfitem" "fmt" @@ -123,7 +124,7 @@ func (g *Guild) Rank() uint16 { 24, 48, 96, 144, 192, 240, 288, 360, 432, 504, 600, 696, 792, 888, 984, 1080, 1200, } - if _config.ErupeConfig.ClientID <= _config.Z2 { + if config.GetConfig().ClientID <= config.Z2 { rpMap = []uint32{ 3500, 6000, 8500, 11000, 13500, 16000, 20000, 24000, 28000, 33000, 38000, 43000, 48000, 55000, 70000, 90000, 120000, @@ -131,21 +132,21 @@ func (g *Guild) Rank() uint16 { } for i, u := range rpMap { if g.RankRP < u { - if _config.ErupeConfig.ClientID <= _config.S6 && i >= 12 { + if config.GetConfig().ClientID <= config.S6 && i >= 12 { return 12 - } else if _config.ErupeConfig.ClientID <= _config.F5 && i >= 13 { + } else if config.GetConfig().ClientID <= config.F5 && i >= 13 { return 13 - } else if _config.ErupeConfig.ClientID <= _config.G32 && i >= 14 { + } else if config.GetConfig().ClientID <= config.G32 && i >= 14 { return 14 } return uint16(i) } } - if _config.ErupeConfig.ClientID <= _config.S6 { + if config.GetConfig().ClientID <= config.S6 { return 12 - } else if _config.ErupeConfig.ClientID <= _config.F5 { + } else if config.GetConfig().ClientID <= config.F5 { return 13 - } else if _config.ErupeConfig.ClientID <= _config.G32 { + } else if config.GetConfig().ClientID <= config.G32 { return 14 } return 17 @@ -189,14 +190,18 @@ SELECT ` func (guild *Guild) Save(s *Session) error { - _, err := s.server.db.Exec(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec(` UPDATE guilds SET main_motto=$2, sub_motto=$3, comment=$4, pugi_name_1=$5, pugi_name_2=$6, pugi_name_3=$7, pugi_outfit_1=$8, pugi_outfit_2=$9, pugi_outfit_3=$10, pugi_outfits=$11, icon=$12, leader_id=$13 WHERE id=$1 `, guild.ID, guild.MainMotto, guild.SubMotto, guild.Comment, guild.PugiName1, guild.PugiName2, guild.PugiName3, guild.PugiOutfit1, guild.PugiOutfit2, guild.PugiOutfit3, guild.PugiOutfits, guild.Icon, guild.GuildLeader.LeaderCharID) if err != nil { - s.logger.Error("failed to update guild data", zap.Error(err), zap.Uint32("guildID", guild.ID)) + s.Logger.Error("failed to update guild data", zap.Error(err), zap.Uint32("guildID", guild.ID)) return err } @@ -210,16 +215,19 @@ func (guild *Guild) CreateApplication(s *Session, charID uint32, applicationType VALUES ($1, $2, $3, $4) ` - var err error + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if transaction == nil { - _, err = s.server.db.Exec(query, guild.ID, charID, s.charID, applicationType) + _, err = database.Exec(query, guild.ID, charID, s.CharID, applicationType) } else { - _, err = transaction.Exec(query, guild.ID, charID, s.charID, applicationType) + _, err = transaction.Exec(query, guild.ID, charID, s.CharID, applicationType) } if err != nil { - s.logger.Error( + s.Logger.Error( "failed to add guild application", zap.Error(err), zap.Uint32("guildID", guild.ID), @@ -232,17 +240,21 @@ func (guild *Guild) CreateApplication(s *Session, charID uint32, applicationType } func (guild *Guild) Disband(s *Session) error { - transaction, err := s.server.db.Begin() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + transaction, err := database.Begin() if err != nil { - s.logger.Error("failed to begin transaction", zap.Error(err)) + s.Logger.Error("failed to begin transaction", zap.Error(err)) return err } _, err = transaction.Exec("DELETE FROM guild_characters WHERE guild_id = $1", guild.ID) if err != nil { - s.logger.Error("failed to remove guild characters", zap.Error(err), zap.Uint32("guildId", guild.ID)) + s.Logger.Error("failed to remove guild characters", zap.Error(err), zap.Uint32("guildId", guild.ID)) rollbackTransaction(s, transaction) return err } @@ -250,7 +262,7 @@ func (guild *Guild) Disband(s *Session) error { _, err = transaction.Exec("DELETE FROM guilds WHERE id = $1", guild.ID) if err != nil { - s.logger.Error("failed to remove guild", zap.Error(err), zap.Uint32("guildID", guild.ID)) + s.Logger.Error("failed to remove guild", zap.Error(err), zap.Uint32("guildID", guild.ID)) rollbackTransaction(s, transaction) return err } @@ -258,7 +270,7 @@ func (guild *Guild) Disband(s *Session) error { _, err = transaction.Exec("DELETE FROM guild_alliances WHERE parent_id=$1", guild.ID) if err != nil { - s.logger.Error("failed to remove guild alliance", zap.Error(err), zap.Uint32("guildID", guild.ID)) + s.Logger.Error("failed to remove guild alliance", zap.Error(err), zap.Uint32("guildID", guild.ID)) rollbackTransaction(s, transaction) return err } @@ -266,7 +278,7 @@ func (guild *Guild) Disband(s *Session) error { _, err = transaction.Exec("UPDATE guild_alliances SET sub1_id=sub2_id, sub2_id=NULL WHERE sub1_id=$1", guild.ID) if err != nil { - s.logger.Error("failed to remove guild from alliance", zap.Error(err), zap.Uint32("guildID", guild.ID)) + s.Logger.Error("failed to remove guild from alliance", zap.Error(err), zap.Uint32("guildID", guild.ID)) rollbackTransaction(s, transaction) return err } @@ -274,7 +286,7 @@ func (guild *Guild) Disband(s *Session) error { _, err = transaction.Exec("UPDATE guild_alliances SET sub2_id=NULL WHERE sub2_id=$1", guild.ID) if err != nil { - s.logger.Error("failed to remove guild from alliance", zap.Error(err), zap.Uint32("guildID", guild.ID)) + s.Logger.Error("failed to remove guild from alliance", zap.Error(err), zap.Uint32("guildID", guild.ID)) rollbackTransaction(s, transaction) return err } @@ -282,20 +294,24 @@ func (guild *Guild) Disband(s *Session) error { err = transaction.Commit() if err != nil { - s.logger.Error("failed to commit transaction", zap.Error(err)) + s.Logger.Error("failed to commit transaction", zap.Error(err)) return err } - s.logger.Info("Character disbanded guild", zap.Uint32("charID", s.charID), zap.Uint32("guildID", guild.ID)) + s.Logger.Info("Character disbanded guild", zap.Uint32("charID", s.CharID), zap.Uint32("guildID", guild.ID)) return nil } func (guild *Guild) RemoveCharacter(s *Session, charID uint32) error { - _, err := s.server.db.Exec("DELETE FROM guild_characters WHERE character_id=$1", charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec("DELETE FROM guild_characters WHERE character_id=$1", charID) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to remove character from guild", zap.Error(err), zap.Uint32("charID", charID), @@ -309,17 +325,21 @@ func (guild *Guild) RemoveCharacter(s *Session, charID uint32) error { } func (guild *Guild) AcceptApplication(s *Session, charID uint32) error { - transaction, err := s.server.db.Begin() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + transaction, err := database.Begin() if err != nil { - s.logger.Error("failed to start db transaction", zap.Error(err)) + s.Logger.Error("failed to start db transaction", zap.Error(err)) return err } _, err = transaction.Exec(`DELETE FROM guild_applications WHERE character_id = $1`, charID) if err != nil { - s.logger.Error("failed to accept character's guild application", zap.Error(err)) + s.Logger.Error("failed to accept character's guild application", zap.Error(err)) rollbackTransaction(s, transaction) return err } @@ -330,7 +350,7 @@ func (guild *Guild) AcceptApplication(s *Session, charID uint32) error { `, guild.ID, charID) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to add applicant to guild", zap.Error(err), zap.Uint32("guildID", guild.ID), @@ -343,7 +363,7 @@ func (guild *Guild) AcceptApplication(s *Session, charID uint32) error { err = transaction.Commit() if err != nil { - s.logger.Error("failed to commit db transaction", zap.Error(err)) + s.Logger.Error("failed to commit db transaction", zap.Error(err)) rollbackTransaction(s, transaction) return err } @@ -354,13 +374,17 @@ func (guild *Guild) AcceptApplication(s *Session, charID uint32) error { // This is relying on the fact that invitation ID is also character ID right now // if invitation ID changes, this will break. func (guild *Guild) CancelInvitation(s *Session, charID uint32) error { - _, err := s.server.db.Exec( + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec( `DELETE FROM guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = 'invited'`, charID, guild.ID, ) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to cancel guild invitation", zap.Error(err), zap.Uint32("guildID", guild.ID), @@ -373,13 +397,17 @@ func (guild *Guild) CancelInvitation(s *Session, charID uint32) error { } func (guild *Guild) RejectApplication(s *Session, charID uint32) error { - _, err := s.server.db.Exec( + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec( `DELETE FROM guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = 'applied'`, charID, guild.ID, ) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to reject guild application", zap.Error(err), zap.Uint32("guildID", guild.ID), @@ -392,10 +420,14 @@ func (guild *Guild) RejectApplication(s *Session, charID uint32) error { } func (guild *Guild) ArrangeCharacters(s *Session, charIDs []uint32) error { - transaction, err := s.server.db.Begin() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + transaction, err := database.Begin() if err != nil { - s.logger.Error("failed to start db transaction", zap.Error(err)) + s.Logger.Error("failed to start db transaction", zap.Error(err)) return err } @@ -406,7 +438,7 @@ func (guild *Guild) ArrangeCharacters(s *Session, charIDs []uint32) error { err = transaction.Rollback() if err != nil { - s.logger.Error("failed to rollback db transaction", zap.Error(err)) + s.Logger.Error("failed to rollback db transaction", zap.Error(err)) } return err @@ -416,7 +448,7 @@ func (guild *Guild) ArrangeCharacters(s *Session, charIDs []uint32) error { err = transaction.Commit() if err != nil { - s.logger.Error("failed to commit db transaction", zap.Error(err)) + s.Logger.Error("failed to commit db transaction", zap.Error(err)) return err } @@ -424,20 +456,24 @@ func (guild *Guild) ArrangeCharacters(s *Session, charIDs []uint32) error { } func (guild *Guild) GetApplicationForCharID(s *Session, charID uint32, applicationType GuildApplicationType) (*GuildApplication, error) { - row := s.server.db.QueryRowx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + row := database.QueryRowx(` SELECT * from guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = $3 `, charID, guild.ID, applicationType) application := &GuildApplication{} - err := row.StructScan(application) + err = row.StructScan(application) if errors.Is(err, sql.ErrNoRows) { return nil, nil } if err != nil { - s.logger.Error( + s.Logger.Error( "failed to retrieve guild application for character", zap.Error(err), zap.Uint32("charID", charID), @@ -450,20 +486,24 @@ func (guild *Guild) GetApplicationForCharID(s *Session, charID uint32, applicati } func (guild *Guild) HasApplicationForCharID(s *Session, charID uint32) (bool, error) { - row := s.server.db.QueryRowx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + row := database.QueryRowx(` SELECT 1 from guild_applications WHERE character_id = $1 AND guild_id = $2 `, charID, guild.ID) num := 0 - err := row.Scan(&num) + err = row.Scan(&num) if errors.Is(err, sql.ErrNoRows) { return false, nil } if err != nil { - s.logger.Error( + s.Logger.Error( "failed to retrieve guild applications for character", zap.Error(err), zap.Uint32("charID", charID), @@ -476,10 +516,14 @@ func (guild *Guild) HasApplicationForCharID(s *Session, charID uint32) (bool, er } func CreateGuild(s *Session, guildName string) (int32, error) { - transaction, err := s.server.db.Begin() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + transaction, err := database.Begin() if err != nil { - s.logger.Error("failed to start db transaction", zap.Error(err)) + s.Logger.Error("failed to start db transaction", zap.Error(err)) return 0, err } @@ -489,11 +533,11 @@ func CreateGuild(s *Session, guildName string) (int32, error) { guildResult, err := transaction.Query( "INSERT INTO guilds (name, leader_id) VALUES ($1, $2) RETURNING id", - guildName, s.charID, + guildName, s.CharID, ) if err != nil { - s.logger.Error("failed to create guild", zap.Error(err)) + s.Logger.Error("failed to create guild", zap.Error(err)) rollbackTransaction(s, transaction) return 0, err } @@ -505,7 +549,7 @@ func CreateGuild(s *Session, guildName string) (int32, error) { err = guildResult.Scan(&guildId) if err != nil { - s.logger.Error("failed to retrieve guild ID", zap.Error(err)) + s.Logger.Error("failed to retrieve guild ID", zap.Error(err)) rollbackTransaction(s, transaction) return 0, err } @@ -513,7 +557,7 @@ func CreateGuild(s *Session, guildName string) (int32, error) { err = guildResult.Close() if err != nil { - s.logger.Error("failed to finalise query", zap.Error(err)) + s.Logger.Error("failed to finalise query", zap.Error(err)) rollbackTransaction(s, transaction) return 0, err } @@ -521,10 +565,10 @@ func CreateGuild(s *Session, guildName string) (int32, error) { _, err = transaction.Exec(` INSERT INTO guild_characters (guild_id, character_id) VALUES ($1, $2) - `, guildId, s.charID) + `, guildId, s.CharID) if err != nil { - s.logger.Error("failed to add character to guild", zap.Error(err)) + s.Logger.Error("failed to add character to guild", zap.Error(err)) rollbackTransaction(s, transaction) return 0, err } @@ -532,7 +576,7 @@ func CreateGuild(s *Session, guildName string) (int32, error) { err = transaction.Commit() if err != nil { - s.logger.Error("failed to commit guild creation", zap.Error(err)) + s.Logger.Error("failed to commit guild creation", zap.Error(err)) return 0, err } @@ -543,19 +587,23 @@ func rollbackTransaction(s *Session, transaction *sql.Tx) { err := transaction.Rollback() if err != nil { - s.logger.Error("failed to rollback transaction", zap.Error(err)) + s.Logger.Error("failed to rollback transaction", zap.Error(err)) } } func GetGuildInfoByID(s *Session, guildID uint32) (*Guild, error) { - rows, err := s.server.db.Queryx(fmt.Sprintf(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(fmt.Sprintf(` %s WHERE g.id = $1 LIMIT 1 `, guildInfoSelectQuery), guildID) if err != nil { - s.logger.Error("failed to retrieve guild", zap.Error(err), zap.Uint32("guildID", guildID)) + s.Logger.Error("failed to retrieve guild", zap.Error(err), zap.Uint32("guildID", guildID)) return nil, err } @@ -571,7 +619,11 @@ func GetGuildInfoByID(s *Session, guildID uint32) (*Guild, error) { } func GetGuildInfoByCharacterId(s *Session, charID uint32) (*Guild, error) { - rows, err := s.server.db.Queryx(fmt.Sprintf(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(fmt.Sprintf(` %s WHERE EXISTS( SELECT 1 @@ -590,7 +642,7 @@ func GetGuildInfoByCharacterId(s *Session, charID uint32) (*Guild, error) { `, guildInfoSelectQuery), charID) if err != nil { - s.logger.Error("failed to retrieve guild for character", zap.Error(err), zap.Uint32("charID", charID)) + s.Logger.Error("failed to retrieve guild for character", zap.Error(err), zap.Uint32("charID", charID)) return nil, err } @@ -611,14 +663,14 @@ func buildGuildObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (*Gu err = result.StructScan(guild) if err != nil { - s.logger.Error("failed to retrieve guild data from database", zap.Error(err)) + s.Logger.Error("failed to retrieve guild data from database", zap.Error(err)) return nil, err } return guild, nil } -func handleMsgMhfCreateGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfCreateGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCreateGuild) guildId, err := CreateGuild(s, pkt.Name) @@ -630,7 +682,7 @@ func handleMsgMhfCreateGuild(s *Session, p mhfpacket.MHFPacket) { // style message, it's better than nothing for now. bf.WriteUint32(0x01010101) - doAckSimpleFail(s, pkt.AckHandle, bf.Data()) + DoAckSimpleFail(s, pkt.AckHandle, bf.Data()) return } @@ -638,26 +690,29 @@ func handleMsgMhfCreateGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(uint32(guildId)) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperateGuild) guild, err := GetGuildInfoByID(s, pkt.GuildID) - characterGuildInfo, err := GetCharacterGuildData(s, s.charID) + characterGuildInfo, err := GetCharacterGuildData(s, s.CharID) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() switch pkt.Action { case mhfpacket.OperateGuildDisband: response := 1 - if guild.LeaderCharID != s.charID { - s.logger.Warn(fmt.Sprintf("character '%d' is attempting to manage guild '%d' without permission", s.charID, guild.ID)) + if guild.LeaderCharID != s.CharID { + s.Logger.Warn(fmt.Sprintf("character '%d' is attempting to manage guild '%d' without permission", s.CharID, guild.ID)) response = 0 } else { err = guild.Disband(s) @@ -686,7 +741,7 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { guild.Save(s) } case mhfpacket.OperateGuildApply: - err = guild.CreateApplication(s, s.charID, GuildApplicationTypeApplied, nil) + err = guild.CreateApplication(s, s.CharID, GuildApplicationTypeApplied, nil) if err == nil { bf.WriteUint32(guild.LeaderCharID) } else { @@ -694,16 +749,16 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { } case mhfpacket.OperateGuildLeave: if characterGuildInfo.IsApplicant { - err = guild.RejectApplication(s, s.charID) + err = guild.RejectApplication(s, s.CharID) } else { - err = guild.RemoveCharacter(s, s.charID) + err = guild.RemoveCharacter(s, s.CharID) } response := 1 if err != nil { response = 0 } else { mail := Mail{ - RecipientID: s.charID, + RecipientID: s.CharID, Subject: "Withdrawal", Body: fmt.Sprintf("You have withdrawn from 「%s」.", guild.Name), IsSystemMessage: true, @@ -714,23 +769,23 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { case mhfpacket.OperateGuildDonateRank: bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, 0)) case mhfpacket.OperateGuildSetApplicationDeny: - s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID) + database.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID) case mhfpacket.OperateGuildSetApplicationAllow: - s.server.db.Exec("UPDATE guilds SET recruiting=true WHERE id=$1", guild.ID) + database.Exec("UPDATE guilds SET recruiting=true WHERE id=$1", guild.ID) case mhfpacket.OperateGuildSetAvoidLeadershipTrue: handleAvoidLeadershipUpdate(s, pkt, true) case mhfpacket.OperateGuildSetAvoidLeadershipFalse: handleAvoidLeadershipUpdate(s, pkt, false) case mhfpacket.OperateGuildUpdateComment: if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } guild.Comment = stringsupport.SJISToUTF8(pkt.Data2.ReadNullTerminatedBytes()) guild.Save(s) case mhfpacket.OperateGuildUpdateMotto: if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } _ = pkt.Data1.ReadUint16() @@ -751,7 +806,7 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 3) case mhfpacket.OperateGuildUnlockOutfit: // TODO: This doesn't implement blocking, if someone unlocked the same outfit at the same time - s.server.db.Exec(`UPDATE guilds SET pugi_outfits=pugi_outfits+$1 WHERE id=$2`, int(math.Pow(float64(pkt.Data1.ReadUint32()), 2)), guild.ID) + database.Exec(`UPDATE guilds SET pugi_outfits=pugi_outfits+$1 WHERE id=$2`, int(math.Pow(float64(pkt.Data1.ReadUint32()), 2)), guild.ID) case mhfpacket.OperateGuildDonateRoom: quantity := uint16(pkt.Data1.ReadUint32()) bf.WriteBytes(handleDonateRP(s, quantity, guild, 2)) @@ -759,20 +814,20 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { quantity := uint16(pkt.Data1.ReadUint32()) bf.WriteBytes(handleDonateRP(s, quantity, guild, 1)) // TODO: Move this value onto rp_yesterday and reset to 0... daily? - s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID) + database.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.CharID) case mhfpacket.OperateGuildEventExchange: rp := uint16(pkt.Data1.ReadUint32()) var balance uint32 - s.server.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance) + database.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance) bf.WriteUint32(balance) default: panic(fmt.Sprintf("unhandled operate guild action '%d'", pkt.Action)) } if len(bf.Data()) > 0 { - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } else { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } } @@ -802,16 +857,20 @@ func handleChangePugi(s *Session, outfit uint8, guild *Guild, num int) { } func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() bf.WriteUint32(0) - saveData, err := GetCharacterSaveData(s, s.charID) + saveData, err := GetCharacterSaveData(s, s.CharID) if err != nil { return bf.Data() } var resetRoom bool if _type == 2 { var currentRP uint16 - s.server.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP) + database.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP) if currentRP+amount >= 30 { amount = 30 - currentRP resetRoom = true @@ -819,17 +878,18 @@ func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte { } saveData.RP -= amount saveData.Save(s) + switch _type { case 0: - s.server.db.Exec(`UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2`, amount, guild.ID) + database.Exec(`UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2`, amount, guild.ID) case 1: - s.server.db.Exec(`UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2`, amount, guild.ID) + database.Exec(`UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2`, amount, guild.ID) case 2: if resetRoom { - s.server.db.Exec(`UPDATE guilds SET room_rp = 0 WHERE id = $1`, guild.ID) - s.server.db.Exec(`UPDATE guilds SET room_expiry = $1 WHERE id = $2`, gametime.TimeAdjusted().Add(time.Hour*24*7), guild.ID) + database.Exec(`UPDATE guilds SET room_rp = 0 WHERE id = $1`, guild.ID) + database.Exec(`UPDATE guilds SET room_expiry = $1 WHERE id = $2`, gametime.TimeAdjusted().Add(time.Hour*24*7), guild.ID) } else { - s.server.db.Exec(`UPDATE guilds SET room_rp = room_rp + $1 WHERE id = $2`, amount, guild.ID) + database.Exec(`UPDATE guilds SET room_rp = room_rp + $1 WHERE id = $2`, amount, guild.ID) } } bf.Seek(0, 0) @@ -838,10 +898,10 @@ func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte { } func handleAvoidLeadershipUpdate(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, avoidLeadership bool) { - characterGuildData, err := GetCharacterGuildData(s, s.charID) + characterGuildData, err := GetCharacterGuildData(s, s.CharID) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } @@ -850,27 +910,27 @@ func handleAvoidLeadershipUpdate(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, err = characterGuildData.Save(s) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperateGuildMember) guild, err := GetGuildInfoByCharacterId(s, pkt.CharID) if err != nil || guild == nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } - actorCharacter, err := GetCharacterGuildData(s, s.charID) + actorCharacter, err := GetCharacterGuildData(s, s.CharID) - if err != nil || (!actorCharacter.IsSubLeader() && guild.LeaderCharID != s.charID) { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + if err != nil || (!actorCharacter.IsSubLeader() && guild.LeaderCharID != s.CharID) { + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } @@ -901,26 +961,26 @@ func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) { IsSystemMessage: true, } default: - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) - s.logger.Warn(fmt.Sprintf("unhandled operateGuildMember action '%d'", pkt.Action)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Warn(fmt.Sprintf("unhandled operateGuildMember action '%d'", pkt.Action)) } if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } else { mail.Send(s, nil) - for _, channel := range s.server.Channels { + for _, channel := range s.Server.Channels { for _, session := range channel.sessions { - if session.charID == pkt.CharID { + if session.CharID == pkt.CharID { SendMailNotification(s, &mail, session) } } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } } -func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfInfoGuild) var guild *Guild @@ -929,7 +989,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { if pkt.GuildID > 0 { guild, err = GetGuildInfoByID(s, pkt.GuildID) } else { - guild, err = GetGuildInfoByCharacterId(s, s.charID) + guild, err = GetGuildInfoByCharacterId(s, s.CharID) } if err == nil && guild != nil { @@ -939,7 +999,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { guildComment := stringsupport.UTF8ToSJIS(guild.Comment) guildLeaderName := stringsupport.UTF8ToSJIS(guild.LeaderName) - characterGuildData, err := GetCharacterGuildData(s, s.charID) + characterGuildData, err := GetCharacterGuildData(s, s.CharID) characterJoinedAt := uint32(0xFFFFFFFF) if characterGuildData != nil && characterGuildData.JoinedAt != nil { @@ -951,7 +1011,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(0) // Count resp.WriteUint8(0) // Unk, read if count == 0. - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) return } @@ -977,7 +1037,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { if characterGuildData == nil || characterGuildData.IsApplicant { bf.WriteUint16(0x00) - } else if guild.LeaderCharID == s.charID { + } else if guild.LeaderCharID == s.CharID { bf.WriteUint16(0x01) } else { bf.WriteUint16(0x02) @@ -1006,15 +1066,15 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(guild.PugiOutfit1) bf.WriteUint8(guild.PugiOutfit2) bf.WriteUint8(guild.PugiOutfit3) - if s.server.erupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { bf.WriteUint8(guild.PugiOutfit1) bf.WriteUint8(guild.PugiOutfit2) bf.WriteUint8(guild.PugiOutfit3) } bf.WriteUint32(guild.PugiOutfits) - limit := s.server.erupeConfig.GameplayOptions.ClanMemberLimits[0][1] - for _, j := range s.server.erupeConfig.GameplayOptions.ClanMemberLimits { + limit := config.GetConfig().GameplayOptions.ClanMemberLimits[0][1] + for _, j := range config.GetConfig().GameplayOptions.ClanMemberLimits { if guild.Rank() >= uint16(j[0]) { limit = j[1] } @@ -1159,23 +1219,26 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint8(0) // Unk - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } else { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 5)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 5)) } } -func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuild) var guilds []*Guild var alliances []*GuildAlliance var rows *sqlx.Rows var err error - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.Type <= 8 { var tempGuilds []*Guild - rows, err = s.server.db.Queryx(guildInfoSelectQuery) + rows, err = database.Queryx(guildInfoSelectQuery) if err == nil { for rows.Next() { guild, err := buildGuildObjectFromDbResult(rows, err, s) @@ -1258,7 +1321,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { if pkt.Type > 8 { var tempAlliances []*GuildAlliance - rows, err = s.server.db.Queryx(allianceInfoSelectQuery) + rows, err = database.Queryx(allianceInfoSelectQuery) if err == nil { for rows.Next() { alliance, _ := buildAllianceObjectFromDbResult(rows, err, s) @@ -1365,25 +1428,25 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfArrangeGuildMember(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfArrangeGuildMember(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfArrangeGuildMember) guild, err := GetGuildInfoByID(s, pkt.GuildID) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to respond to ArrangeGuildMember message", - zap.Uint32("charID", s.charID), + zap.Uint32("charID", s.CharID), ) return } - if guild.LeaderCharID != s.charID { - s.logger.Error("non leader attempting to rearrange guild members!", - zap.Uint32("charID", s.charID), + if guild.LeaderCharID != s.CharID { + s.Logger.Error("non leader attempting to rearrange guild members!", + zap.Uint32("charID", s.CharID), zap.Uint32("guildID", guild.ID), ) return @@ -1392,18 +1455,18 @@ func handleMsgMhfArrangeGuildMember(s *Session, p mhfpacket.MHFPacket) { err = guild.ArrangeCharacters(s, pkt.CharIDs) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to respond to ArrangeGuildMember message", - zap.Uint32("charID", s.charID), + zap.Uint32("charID", s.CharID), zap.Uint32("guildID", guild.ID), ) return } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuildMember) var guild *Guild @@ -1412,13 +1475,13 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { if pkt.GuildID > 0 { guild, err = GetGuildInfoByID(s, pkt.GuildID) } else { - guild, err = GetGuildInfoByCharacterId(s, s.charID) + guild, err = GetGuildInfoByCharacterId(s, s.CharID) } if guild != nil { - isApplicant, _ := guild.HasApplicationForCharID(s, s.charID) + isApplicant, _ := guild.HasApplicationForCharID(s, s.CharID) if isApplicant { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) return } } @@ -1428,24 +1491,24 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { } if err != nil { - s.logger.Warn("failed to retrieve guild sending no result message") - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) + s.Logger.Warn("failed to retrieve guild sending no result message") + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) return } else if guild == nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) return } guildMembers, err := GetGuildMembers(s, guild.ID, false) if err != nil { - s.logger.Error("failed to retrieve guild") + s.Logger.Error("failed to retrieve guild") return } alliance, err := GetAllianceData(s, guild.AllianceID) if err != nil { - s.logger.Error("Failed to get alliance data") + s.Logger.Error("Failed to get alliance data") return } @@ -1460,10 +1523,10 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { for _, member := range guildMembers { bf.WriteUint32(member.CharID) bf.WriteUint16(member.HR) - if s.server.erupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { bf.WriteUint16(member.GR) } - if s.server.erupeConfig.ClientID < _config.ZZ { + if config.GetConfig().ClientID < config.ZZ { // Magnet Spike crash workaround bf.WriteUint16(0) } else { @@ -1521,18 +1584,18 @@ func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(member.RPYesterday) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildManageRight) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if guild == nil && s.prevGuildID != 0 { guild, err = GetGuildInfoByID(s, s.prevGuildID) s.prevGuildID = 0 if guild == nil || err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } } @@ -1545,28 +1608,28 @@ func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { bf.WriteBool(member.Recruiter) bf.WriteBytes(make([]byte, 3)) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfGetUdGuildMapInfo(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetUdGuildMapInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdGuildMapInfo) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildTargetMemberNum) var guild *Guild var err error if pkt.GuildID == 0x0 { - guild, err = GetGuildInfoByCharacterId(s, s.charID) + guild, err = GetGuildInfoByCharacterId(s, s.CharID) } else { guild, err = GetGuildInfoByID(s, pkt.GuildID) } if err != nil || guild == nil { - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02}) return } @@ -1575,13 +1638,17 @@ func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(0x0) bf.WriteUint16(guild.MemberCount - 1) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack { var data []byte var items []mhfitem.MHFItemStack - s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data) if len(data) > 0 { box := byteframe.NewByteFrameFromBytes(data) numStacks := box.ReadUint16() @@ -1593,22 +1660,26 @@ func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack { return items } -func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuildItem) items := guildGetItems(s, pkt.GuildID) bf := byteframe.NewByteFrame() bf.WriteBytes(mhfitem.SerializeWarehouseItems(items)) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateGuildItem) newStacks := mhfitem.DiffItemStacks(guildGetItems(s, pkt.GuildID), pkt.UpdatedItems) - s.server.db.Exec(`UPDATE guilds SET item_box=$1 WHERE id=$2`, mhfitem.SerializeWarehouseItems(newStacks), pkt.GuildID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE guilds SET item_box=$1 WHERE id=$2`, mhfitem.SerializeWarehouseItems(newStacks), pkt.GuildID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateGuildIcon) guild, err := GetGuildInfoByID(s, pkt.GuildID) @@ -1617,19 +1688,19 @@ func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { panic(err) } - characterInfo, err := GetCharacterGuildData(s, s.charID) + characterInfo, err := GetCharacterGuildData(s, s.CharID) if err != nil { panic(err) } if !characterInfo.IsSubLeader() && !characterInfo.IsLeader { - s.logger.Warn( + s.Logger.Warn( "character without leadership attempting to update guild icon", zap.Uint32("guildID", guild.ID), - zap.Uint32("charID", s.charID), + zap.Uint32("charID", s.CharID), ) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } @@ -1657,14 +1728,14 @@ func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { err = guild.Save(s) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfReadGuildcard(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfReadGuildcard(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfReadGuildcard) resp := byteframe.NewByteFrame() @@ -1677,7 +1748,7 @@ func handleMsgMhfReadGuildcard(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(0) resp.WriteUint32(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } type GuildMission struct { @@ -1692,7 +1763,7 @@ type GuildMission struct { RewardLevel uint16 } -func handleMsgMhfGetGuildMissionList(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildMissionList(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildMissionList) bf := byteframe.NewByteFrame() missions := []GuildMission{ @@ -1724,29 +1795,29 @@ func handleMsgMhfGetGuildMissionList(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(mission.RewardLevel) bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfGetGuildMissionRecord(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildMissionRecord(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildMissionRecord) // No guild mission records = 0x190 empty bytes - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x190)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x190)) } -func handleMsgMhfAddGuildMissionCount(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAddGuildMissionCount(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAddGuildMissionCount) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfSetGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfSetGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetGuildMissionTarget) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfCancelGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfCancelGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCancelGuildMissionTarget) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type GuildMeal struct { @@ -1756,13 +1827,17 @@ type GuildMeal struct { CreatedAt time.Time `db:"created_at"` } -func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadGuildCooking) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) - data, err := s.server.db.Queryx("SELECT id, meal_id, level, created_at FROM guild_meals WHERE guild_id = $1", guild.ID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get guild meals from db", zap.Error(err)) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) + data, err := database.Queryx("SELECT id, meal_id, level, created_at FROM guild_meals WHERE guild_id = $1", guild.ID) + if err != nil { + s.Logger.Error("Failed to get guild meals from db", zap.Error(err)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) return } var meals []GuildMeal @@ -1784,17 +1859,21 @@ func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(meal.Level) bf.WriteUint32(uint32(meal.CreatedAt.Unix())) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegistGuildCooking) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) - startTime := gametime.TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.ClanMealDuration-3600) * time.Second) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) + startTime := gametime.TimeAdjusted().Add(time.Duration(config.GetConfig().GameplayOptions.ClanMealDuration-3600) * time.Second) if pkt.OverwriteID != 0 { - s.server.db.Exec("UPDATE guild_meals SET meal_id = $1, level = $2, created_at = $3 WHERE id = $4", pkt.MealID, pkt.Success, startTime, pkt.OverwriteID) + database.Exec("UPDATE guild_meals SET meal_id = $1, level = $2, created_at = $3 WHERE id = $4", pkt.MealID, pkt.Success, startTime, pkt.OverwriteID) } else { - s.server.db.QueryRow("INSERT INTO guild_meals (guild_id, meal_id, level, created_at) VALUES ($1, $2, $3, $4) RETURNING id", guild.ID, pkt.MealID, pkt.Success, startTime).Scan(&pkt.OverwriteID) + database.QueryRow("INSERT INTO guild_meals (guild_id, meal_id, level, created_at) VALUES ($1, $2, $3, $4) RETURNING id", guild.ID, pkt.MealID, pkt.Success, startTime).Scan(&pkt.OverwriteID) } bf := byteframe.NewByteFrame() bf.WriteUint16(1) @@ -1802,37 +1881,41 @@ func handleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(uint32(pkt.MealID)) bf.WriteUint32(uint32(pkt.Success)) bf.WriteUint32(uint32(startTime.Unix())) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfGetGuildWeeklyBonusMaster(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildWeeklyBonusMaster(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildWeeklyBonusMaster) // Values taken from brand new guild capture - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 40)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 40)) } -func handleMsgMhfGetGuildWeeklyBonusActiveCount(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildWeeklyBonusActiveCount(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildWeeklyBonusActiveCount) bf := byteframe.NewByteFrame() bf.WriteUint8(60) // Active count bf.WriteUint8(60) // Current active count bf.WriteUint8(0) // New active count - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGuildHuntdata) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() switch pkt.Operation { case 0: // Acquire - s.server.db.Exec(`UPDATE guild_characters SET box_claimed=$1 WHERE character_id=$2`, gametime.TimeAdjusted(), s.charID) + database.Exec(`UPDATE guild_characters SET box_claimed=$1 WHERE character_id=$2`, gametime.TimeAdjusted(), s.CharID) case 1: // Enumerate bf.WriteUint8(0) // Entries - rows, err := s.server.db.Query(`SELECT kl.id, kl.monster FROM kill_logs kl + rows, err := database.Query(`SELECT kl.id, kl.monster FROM kill_logs kl INNER JOIN guild_characters gc ON kl.character_id = gc.character_id WHERE gc.guild_id=$1 AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2) - `, pkt.GuildID, s.charID) + `, pkt.GuildID, s.CharID) if err == nil { var count uint8 var huntID, monID uint32 @@ -1854,14 +1937,14 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(count) } case 2: // Check - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err == nil { var count uint8 - err = s.server.db.QueryRow(`SELECT COUNT(*) FROM kill_logs kl + err = database.QueryRow(`SELECT COUNT(*) FROM kill_logs kl INNER JOIN guild_characters gc ON kl.character_id = gc.character_id WHERE gc.guild_id=$1 AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2) - `, guild.ID, s.charID).Scan(&count) + `, guild.ID, s.CharID).Scan(&count) if err == nil && count > 0 { bf.WriteBool(true) } else { @@ -1871,7 +1954,7 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { bf.WriteBool(false) } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type MessageBoardPost struct { @@ -1884,19 +1967,23 @@ type MessageBoardPost struct { LikedBy string `db:"liked_by"` } -func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuildMessageBoard) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) if pkt.BoardType == 1 { pkt.MaxPosts = 4 } - msgs, err := s.server.db.Queryx("SELECT id, stamp_id, title, body, author_id, created_at, liked_by FROM guild_posts WHERE guild_id = $1 AND post_type = $2 ORDER BY created_at DESC", guild.ID, int(pkt.BoardType)) + msgs, err := database.Queryx("SELECT id, stamp_id, title, body, author_id, created_at, liked_by FROM guild_posts WHERE guild_id = $1 AND post_type = $2 ORDER BY created_at DESC", guild.ID, int(pkt.BoardType)) if err != nil { - s.logger.Error("Failed to get guild messages from db", zap.Error(err)) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to get guild messages from db", zap.Error(err)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } - s.server.db.Exec("UPDATE characters SET guild_post_checked = now() WHERE id = $1", s.charID) + database.Exec("UPDATE characters SET guild_post_checked = now() WHERE id = $1", s.CharID) bf := byteframe.NewByteFrame() var postCount uint32 for msgs.Next() { @@ -1911,7 +1998,7 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(0) bf.WriteUint32(uint32(postData.Timestamp.Unix())) bf.WriteUint32(uint32(stringsupport.CSVLength(postData.LikedBy))) - bf.WriteBool(stringsupport.CSVContains(postData.LikedBy, int(s.charID))) + bf.WriteBool(stringsupport.CSVContains(postData.LikedBy, int(s.CharID))) bf.WriteUint32(postData.StampID) ps.Uint32(bf, postData.Title, true) ps.Uint32(bf, postData.Body, true) @@ -1919,106 +2006,114 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { data := byteframe.NewByteFrame() data.WriteUint32(postCount) data.WriteBytes(bf.Data()) - doAckBufSucceed(s, pkt.AckHandle, data.Data()) + DoAckBufSucceed(s, pkt.AckHandle, data.Data()) } -func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateGuildMessageBoard) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, err := GetGuildInfoByCharacterId(s, s.CharID) applicant := false if guild != nil { - applicant, _ = guild.HasApplicationForCharID(s, s.charID) + applicant, _ = guild.HasApplicationForCharID(s, s.CharID) } if err != nil || guild == nil || applicant { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } switch pkt.MessageOp { case 0: // Create message - s.server.db.Exec("INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)", guild.ID, s.charID, pkt.StampID, pkt.PostType, pkt.Title, pkt.Body) + database.Exec("INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)", guild.ID, s.CharID, pkt.StampID, pkt.PostType, pkt.Title, pkt.Body) // TODO: if there are too many messages, purge excess case 1: // Delete message - s.server.db.Exec("DELETE FROM guild_posts WHERE id = $1", pkt.PostID) + database.Exec("DELETE FROM guild_posts WHERE id = $1", pkt.PostID) case 2: // Update message - s.server.db.Exec("UPDATE guild_posts SET title = $1, body = $2 WHERE id = $3", pkt.Title, pkt.Body, pkt.PostID) + database.Exec("UPDATE guild_posts SET title = $1, body = $2 WHERE id = $3", pkt.Title, pkt.Body, pkt.PostID) case 3: // Update stamp - s.server.db.Exec("UPDATE guild_posts SET stamp_id = $1 WHERE id = $2", pkt.StampID, pkt.PostID) + database.Exec("UPDATE guild_posts SET stamp_id = $1 WHERE id = $2", pkt.StampID, pkt.PostID) case 4: // Like message var likedBy string - err := s.server.db.QueryRow("SELECT liked_by FROM guild_posts WHERE id = $1", pkt.PostID).Scan(&likedBy) + err := database.QueryRow("SELECT liked_by FROM guild_posts WHERE id = $1", pkt.PostID).Scan(&likedBy) if err != nil { - s.logger.Error("Failed to get guild message like data from db", zap.Error(err)) + s.Logger.Error("Failed to get guild message like data from db", zap.Error(err)) } else { if pkt.LikeState { - likedBy = stringsupport.CSVAdd(likedBy, int(s.charID)) - s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID) + likedBy = stringsupport.CSVAdd(likedBy, int(s.CharID)) + database.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID) } else { - likedBy = stringsupport.CSVRemove(likedBy, int(s.charID)) - s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID) + likedBy = stringsupport.CSVRemove(likedBy, int(s.CharID)) + database.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID) } } case 5: // Check for new messages var timeChecked time.Time var newPosts int - err := s.server.db.QueryRow("SELECT guild_post_checked FROM characters WHERE id = $1", s.charID).Scan(&timeChecked) + err := database.QueryRow("SELECT guild_post_checked FROM characters WHERE id = $1", s.CharID).Scan(&timeChecked) if err == nil { - s.server.db.QueryRow("SELECT COUNT(*) FROM guild_posts WHERE guild_id = $1 AND (EXTRACT(epoch FROM created_at)::int) > $2", guild.ID, timeChecked.Unix()).Scan(&newPosts) + database.QueryRow("SELECT COUNT(*) FROM guild_posts WHERE guild_id = $1 AND (EXTRACT(epoch FROM created_at)::int) > $2", guild.ID, timeChecked.Unix()).Scan(&newPosts) if newPosts > 0 { - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) return } } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfEntryRookieGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEntryRookieGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEntryRookieGuild) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfUpdateForceGuildRank(s *Session, p mhfpacket.MHFPacket) {} +func HandleMsgMhfUpdateForceGuildRank(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfAddGuildWeeklyBonusExceptionalUser(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAddGuildWeeklyBonusExceptionalUser(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAddGuildWeeklyBonusExceptionalUser) // TODO: record pkt.NumUsers to DB // must use addition - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } -func handleMsgMhfGenerateUdGuildMap(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGenerateUdGuildMap(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGenerateUdGuildMap) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfUpdateGuild(s *Session, p mhfpacket.MHFPacket) {} +func HandleMsgMhfUpdateGuild(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfSetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfSetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetGuildManageRight) - s.server.db.Exec("UPDATE guild_characters SET recruiter=$1 WHERE character_id=$2", pkt.Allowed, pkt.CharID) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("UPDATE guild_characters SET recruiter=$1 WHERE character_id=$2", pkt.Allowed, pkt.CharID) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfCheckMonthlyItem(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfCheckMonthlyItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCheckMonthlyItem) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) // TODO: Implement month-by-month tracker, 0 = Not claimed, 1 = Claimed // Also handles HLC and EXC items, IDs = 064D, 076B } -func handleMsgMhfAcquireMonthlyItem(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAcquireMonthlyItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireMonthlyItem) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfEnumerateInvGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEnumerateInvGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateInvGuild) stubEnumerateNoResults(s, pkt.AckHandle) } -func handleMsgMhfOperationInvGuild(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfOperationInvGuild(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperationInvGuild) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {} +func HandleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_guild_adventure.go b/server/channelserver/handlers_guild_adventure.go index b8d7e8677..bdf188253 100644 --- a/server/channelserver/handlers_guild_adventure.go +++ b/server/channelserver/handlers_guild_adventure.go @@ -1,10 +1,12 @@ package channelserver import ( + "fmt" "time" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/stringsupport" @@ -20,13 +22,17 @@ type GuildAdventure struct { CollectedBy string `db:"collected_by"` } -func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadGuildAdventure) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) - data, err := s.server.db.Queryx("SELECT id, destination, charge, depart, return, collected_by FROM guild_adventures WHERE guild_id = $1", guild.ID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get guild adventures from db", zap.Error(err)) - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) + data, err := database.Queryx("SELECT id, destination, charge, depart, return, collected_by FROM guild_adventures WHERE guild_id = $1", guild.ID) + if err != nil { + s.Logger.Error("Failed to get guild adventures from db", zap.Error(err)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } temp := byteframe.NewByteFrame() @@ -43,55 +49,71 @@ func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) { temp.WriteUint32(adventureData.Charge) temp.WriteUint32(adventureData.Depart) temp.WriteUint32(adventureData.Return) - temp.WriteBool(stringsupport.CSVContains(adventureData.CollectedBy, int(s.charID))) + temp.WriteBool(stringsupport.CSVContains(adventureData.CollectedBy, int(s.CharID))) } bf := byteframe.NewByteFrame() bf.WriteUint8(uint8(count)) bf.WriteBytes(temp.Data()) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfRegistGuildAdventure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfRegistGuildAdventure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegistGuildAdventure) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) - _, err := s.server.db.Exec("INSERT INTO guild_adventures (guild_id, destination, depart, return) VALUES ($1, $2, $3, $4)", guild.ID, pkt.Destination, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(6*time.Hour).Unix()) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to register guild adventure", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) + _, err = database.Exec("INSERT INTO guild_adventures (guild_id, destination, depart, return) VALUES ($1, $2, $3, $4)", guild.ID, pkt.Destination, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(6*time.Hour).Unix()) + if err != nil { + s.Logger.Error("Failed to register guild adventure", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfAcquireGuildAdventure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAcquireGuildAdventure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireGuildAdventure) - var collectedBy string - err := s.server.db.QueryRow("SELECT collected_by FROM guild_adventures WHERE id = $1", pkt.ID).Scan(&collectedBy) + database, err := db.GetDB() if err != nil { - s.logger.Error("Error parsing adventure collected by", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var collectedBy string + err = database.QueryRow("SELECT collected_by FROM guild_adventures WHERE id = $1", pkt.ID).Scan(&collectedBy) + if err != nil { + s.Logger.Error("Error parsing adventure collected by", zap.Error(err)) } else { - collectedBy = stringsupport.CSVAdd(collectedBy, int(s.charID)) - _, err := s.server.db.Exec("UPDATE guild_adventures SET collected_by = $1 WHERE id = $2", collectedBy, pkt.ID) + collectedBy = stringsupport.CSVAdd(collectedBy, int(s.CharID)) + _, err := database.Exec("UPDATE guild_adventures SET collected_by = $1 WHERE id = $2", collectedBy, pkt.ID) if err != nil { - s.logger.Error("Failed to collect adventure in db", zap.Error(err)) + s.Logger.Error("Failed to collect adventure in db", zap.Error(err)) } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfChargeGuildAdventure) - _, err := s.server.db.Exec("UPDATE guild_adventures SET charge = charge + $1 WHERE id = $2", pkt.Amount, pkt.ID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to charge guild adventure", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + _, err = database.Exec("UPDATE guild_adventures SET charge = charge + $1 WHERE id = $2", pkt.Amount, pkt.ID) + if err != nil { + s.Logger.Error("Failed to charge guild adventure", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfRegistGuildAdventureDiva(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfRegistGuildAdventureDiva(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegistGuildAdventureDiva) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) - _, err := s.server.db.Exec("INSERT INTO guild_adventures (guild_id, destination, charge, depart, return) VALUES ($1, $2, $3, $4, $5)", guild.ID, pkt.Destination, pkt.Charge, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(1*time.Hour).Unix()) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to register guild adventure", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) + _, err = database.Exec("INSERT INTO guild_adventures (guild_id, destination, charge, depart, return) VALUES ($1, $2, $3, $4, $5)", guild.ID, pkt.Destination, pkt.Charge, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(1*time.Hour).Unix()) + if err != nil { + s.Logger.Error("Failed to register guild adventure", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_guild_alliance.go b/server/channelserver/handlers_guild_alliance.go index 94ba123a7..c8c4c0ed3 100644 --- a/server/channelserver/handlers_guild_alliance.go +++ b/server/channelserver/handlers_guild_alliance.go @@ -2,6 +2,7 @@ package channelserver import ( "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" ps "erupe-ce/utils/pascalstring" "fmt" "time" @@ -45,12 +46,16 @@ type GuildAlliance struct { } func GetAllianceData(s *Session, AllianceID uint32) (*GuildAlliance, error) { - rows, err := s.server.db.Queryx(fmt.Sprintf(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(fmt.Sprintf(` %s WHERE ga.id = $1 `, allianceInfoSelectQuery), AllianceID) if err != nil { - s.logger.Error("Failed to retrieve alliance data from database", zap.Error(err)) + s.Logger.Error("Failed to retrieve alliance data from database", zap.Error(err)) return nil, err } defer rows.Close() @@ -68,13 +73,13 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) ( err = result.StructScan(alliance) if err != nil { - s.logger.Error("failed to retrieve alliance from database", zap.Error(err)) + s.Logger.Error("failed to retrieve alliance from database", zap.Error(err)) return nil, err } parentGuild, err := GetGuildInfoByID(s, alliance.ParentGuildID) if err != nil { - s.logger.Error("Failed to get parent guild info", zap.Error(err)) + s.Logger.Error("Failed to get parent guild info", zap.Error(err)) return nil, err } else { alliance.ParentGuild = *parentGuild @@ -84,7 +89,7 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) ( if alliance.SubGuild1ID > 0 { subGuild1, err := GetGuildInfoByID(s, alliance.SubGuild1ID) if err != nil { - s.logger.Error("Failed to get sub guild 1 info", zap.Error(err)) + s.Logger.Error("Failed to get sub guild 1 info", zap.Error(err)) return nil, err } else { alliance.SubGuild1 = *subGuild1 @@ -95,7 +100,7 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) ( if alliance.SubGuild2ID > 0 { subGuild2, err := GetGuildInfoByID(s, alliance.SubGuild2ID) if err != nil { - s.logger.Error("Failed to get sub guild 2 info", zap.Error(err)) + s.Logger.Error("Failed to get sub guild 2 info", zap.Error(err)) return nil, err } else { alliance.SubGuild2 = *subGuild2 @@ -106,92 +111,99 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) ( return alliance, nil } -func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCreateJoint) - _, err := s.server.db.Exec("INSERT INTO guild_alliances (name, parent_id) VALUES ($1, $2)", pkt.Name, pkt.GuildID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to create guild alliance in db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x01, 0x01, 0x01, 0x01}) + _, err = database.Exec("INSERT INTO guild_alliances (name, parent_id) VALUES ($1, $2)", pkt.Name, pkt.GuildID) + if err != nil { + s.Logger.Error("Failed to create guild alliance in db", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x01, 0x01, 0x01, 0x01}) } -func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperateJoint) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } guild, err := GetGuildInfoByID(s, pkt.GuildID) if err != nil { - s.logger.Error("Failed to get guild info", zap.Error(err)) + s.Logger.Error("Failed to get guild info", zap.Error(err)) } alliance, err := GetAllianceData(s, pkt.AllianceID) if err != nil { - s.logger.Error("Failed to get alliance info", zap.Error(err)) + s.Logger.Error("Failed to get alliance info", zap.Error(err)) } switch pkt.Action { case mhfpacket.OPERATE_JOINT_DISBAND: - if guild.LeaderCharID == s.charID && alliance.ParentGuildID == guild.ID { - _, err = s.server.db.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID) + if guild.LeaderCharID == s.CharID && alliance.ParentGuildID == guild.ID { + _, err = database.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID) if err != nil { - s.logger.Error("Failed to disband alliance", zap.Error(err)) + s.Logger.Error("Failed to disband alliance", zap.Error(err)) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } else { - s.logger.Warn( + s.Logger.Warn( "Non-owner of alliance attempted disband", - zap.Uint32("CharID", s.charID), + zap.Uint32("CharID", s.CharID), zap.Uint32("AllyID", alliance.ID), ) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } case mhfpacket.OPERATE_JOINT_LEAVE: - if guild.LeaderCharID == s.charID { + if guild.LeaderCharID == s.CharID { if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 { - s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID) + database.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID) } else if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 { - s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID) + database.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID) } else { - s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID) + database.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID) } // TODO: Handle deleting Alliance applications - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } else { - s.logger.Warn( + s.Logger.Warn( "Non-owner of guild attempted alliance leave", - zap.Uint32("CharID", s.charID), + zap.Uint32("CharID", s.CharID), ) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } case mhfpacket.OPERATE_JOINT_KICK: - if alliance.ParentGuild.LeaderCharID == s.charID { + if alliance.ParentGuild.LeaderCharID == s.CharID { kickedGuildID := pkt.Data1.ReadUint32() if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 { - s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID) + database.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID) } else if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 { - s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID) + database.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID) } else { - s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID) + database.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } else { - s.logger.Warn( + s.Logger.Warn( "Non-owner of alliance attempted kick", - zap.Uint32("CharID", s.charID), + zap.Uint32("CharID", s.CharID), zap.Uint32("AllyID", alliance.ID), ) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } default: - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action)) } } -func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfInfoJoint) bf := byteframe.NewByteFrame() alliance, err := GetAllianceData(s, pkt.AllianceID) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } else { bf.WriteUint32(alliance.ID) bf.WriteUint32(uint32(alliance.CreatedAt.Unix())) @@ -229,6 +241,6 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) { ps.Uint16(bf, alliance.SubGuild2.Name, true) ps.Uint16(bf, alliance.SubGuild2.LeaderName, true) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } } diff --git a/server/channelserver/handlers_guild_member.go b/server/channelserver/handlers_guild_member.go index f4cb04175..08061263e 100644 --- a/server/channelserver/handlers_guild_member.go +++ b/server/channelserver/handlers_guild_member.go @@ -1,6 +1,7 @@ package channelserver import ( + "erupe-ce/utils/db" "fmt" "time" @@ -46,10 +47,14 @@ func (gm *GuildMember) IsSubLeader() bool { } func (gm *GuildMember) Save(s *Session) error { - _, err := s.server.db.Exec("UPDATE guild_characters SET avoid_leadership=$1, order_index=$2 WHERE character_id=$3", gm.AvoidLeadership, gm.OrderIndex, gm.CharID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec("UPDATE guild_characters SET avoid_leadership=$1, order_index=$2 WHERE character_id=$3", gm.AvoidLeadership, gm.OrderIndex, gm.CharID) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to update guild member data", zap.Error(err), zap.Uint32("charID", gm.CharID), @@ -87,13 +92,17 @@ SELECT * FROM ( ` func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) { - rows, err := s.server.db.Queryx(fmt.Sprintf(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(fmt.Sprintf(` %s WHERE guild_id = $1 AND is_applicant = $2 `, guildMembersSelectSQL), guildID, applicants) if err != nil { - s.logger.Error("failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID)) + s.Logger.Error("failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID)) return nil, err } @@ -115,10 +124,15 @@ func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMembe } func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) { - rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID) + + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID) if err != nil { - s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID)) + s.Logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID)) return nil, err } @@ -139,7 +153,7 @@ func buildGuildMemberObjectFromDBResult(rows *sqlx.Rows, err error, s *Session) err = rows.StructScan(&memberData) if err != nil { - s.logger.Error("failed to retrieve guild data from database", zap.Error(err)) + s.Logger.Error("failed to retrieve guild data from database", zap.Error(err)) return nil, err } diff --git a/server/channelserver/handlers_guild_scout.go b/server/channelserver/handlers_guild_scout.go index 5406e984c..bdcd2eb6f 100644 --- a/server/channelserver/handlers_guild_scout.go +++ b/server/channelserver/handlers_guild_scout.go @@ -3,6 +3,7 @@ package channelserver import ( "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/stringsupport" "fmt" @@ -11,41 +12,44 @@ import ( "go.uber.org/zap" ) -func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostGuildScout) - actorCharGuildData, err := GetCharacterGuildData(s, s.charID) + actorCharGuildData, err := GetCharacterGuildData(s, s.CharID) if err != nil { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) panic(err) } if actorCharGuildData == nil || !actorCharGuildData.CanRecruit() { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) return } guildInfo, err := GetGuildInfoByID(s, actorCharGuildData.GuildID) if err != nil { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) panic(err) } hasApplication, err := guildInfo.HasApplicationForCharID(s, pkt.CharID) if err != nil { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) panic(err) } if hasApplication { - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x04}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x04}) return } - - transaction, err := s.server.db.Begin() + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + transaction, err := database.Begin() if err != nil { panic(err) @@ -55,16 +59,16 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { if err != nil { rollbackTransaction(s, transaction) - doAckBufFail(s, pkt.AckHandle, nil) + DoAckBufFail(s, pkt.AckHandle, nil) panic(err) } mail := &Mail{ - SenderID: s.charID, + SenderID: s.CharID, RecipientID: pkt.CharID, - Subject: s.server.i18n.guild.invite.title, + Subject: s.Server.i18n.guild.invite.title, Body: fmt.Sprintf( - s.server.i18n.guild.invite.body, + s.Server.i18n.guild.invite.body, guildInfo.Name, ), IsGuildInvite: true, @@ -74,52 +78,52 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { if err != nil { rollbackTransaction(s, transaction) - doAckBufFail(s, pkt.AckHandle, nil) + DoAckBufFail(s, pkt.AckHandle, nil) return } err = transaction.Commit() if err != nil { - doAckBufFail(s, pkt.AckHandle, nil) + DoAckBufFail(s, pkt.AckHandle, nil) panic(err) } - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } -func handleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCancelGuildScout) - guildCharData, err := GetCharacterGuildData(s, s.charID) + guildCharData, err := GetCharacterGuildData(s, s.CharID) if err != nil { panic(err) } if guildCharData == nil || !guildCharData.CanRecruit() { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) return } guild, err := GetGuildInfoByID(s, guildCharData.GuildID) if err != nil { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) return } err = guild.CancelInvitation(s, pkt.InvitationID) if err != nil { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) return } - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAnswerGuildScout) bf := byteframe.NewByteFrame() guild, err := GetGuildInfoByCharacterId(s, pkt.LeaderID) @@ -128,84 +132,87 @@ func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) { panic(err) } - app, err := guild.GetApplicationForCharID(s, s.charID, GuildApplicationTypeInvited) + app, err := guild.GetApplicationForCharID(s, s.CharID, GuildApplicationTypeInvited) if app == nil || err != nil { - s.logger.Warn( + s.Logger.Warn( "Guild invite missing, deleted?", zap.Error(err), zap.Uint32("guildID", guild.ID), - zap.Uint32("charID", s.charID), + zap.Uint32("charID", s.CharID), ) bf.WriteUint32(7) bf.WriteUint32(guild.ID) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) return } var mail []Mail if pkt.Answer { - err = guild.AcceptApplication(s, s.charID) + err = guild.AcceptApplication(s, s.CharID) mail = append(mail, Mail{ - RecipientID: s.charID, - Subject: s.server.i18n.guild.invite.success.title, - Body: fmt.Sprintf(s.server.i18n.guild.invite.success.body, guild.Name), + RecipientID: s.CharID, + Subject: s.Server.i18n.guild.invite.success.title, + Body: fmt.Sprintf(s.Server.i18n.guild.invite.success.body, guild.Name), IsSystemMessage: true, }) mail = append(mail, Mail{ - SenderID: s.charID, + SenderID: s.CharID, RecipientID: pkt.LeaderID, - Subject: s.server.i18n.guild.invite.accepted.title, - Body: fmt.Sprintf(s.server.i18n.guild.invite.accepted.body, guild.Name), + Subject: s.Server.i18n.guild.invite.accepted.title, + Body: fmt.Sprintf(s.Server.i18n.guild.invite.accepted.body, guild.Name), IsSystemMessage: true, }) } else { - err = guild.RejectApplication(s, s.charID) + err = guild.RejectApplication(s, s.CharID) mail = append(mail, Mail{ - RecipientID: s.charID, - Subject: s.server.i18n.guild.invite.rejected.title, - Body: fmt.Sprintf(s.server.i18n.guild.invite.rejected.body, guild.Name), + RecipientID: s.CharID, + Subject: s.Server.i18n.guild.invite.rejected.title, + Body: fmt.Sprintf(s.Server.i18n.guild.invite.rejected.body, guild.Name), IsSystemMessage: true, }) mail = append(mail, Mail{ - SenderID: s.charID, + SenderID: s.CharID, RecipientID: pkt.LeaderID, - Subject: s.server.i18n.guild.invite.declined.title, - Body: fmt.Sprintf(s.server.i18n.guild.invite.declined.body, guild.Name), + Subject: s.Server.i18n.guild.invite.declined.title, + Body: fmt.Sprintf(s.Server.i18n.guild.invite.declined.body, guild.Name), IsSystemMessage: true, }) } if err != nil { bf.WriteUint32(7) bf.WriteUint32(guild.ID) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } else { bf.WriteUint32(0) bf.WriteUint32(guild.ID) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) for _, m := range mail { m.Send(s, nil) } } } -func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildScoutList) - guildInfo, err := GetGuildInfoByCharacterId(s, s.charID) + guildInfo, err := GetGuildInfoByCharacterId(s, s.CharID) if guildInfo == nil && s.prevGuildID == 0 { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } else { guildInfo, err = GetGuildInfoByID(s, s.prevGuildID) if guildInfo == nil || err != nil { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } } - - rows, err := s.server.db.Queryx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(` SELECT c.id, c.name, c.hr, c.gr, ga.actor_id FROM guild_applications ga JOIN characters c ON c.id = ga.character_id @@ -213,8 +220,8 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { `, guildInfo.ID) if err != nil { - s.logger.Error("failed to retrieve scouted characters", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("failed to retrieve scouted characters", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } @@ -237,7 +244,7 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { err = rows.Scan(&charID, &charName, &HR, &GR, &actorID) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, nil) + DoAckSimpleFail(s, pkt.AckHandle, nil) continue } @@ -262,25 +269,28 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(count) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetRejectGuildScout) - - row := s.server.db.QueryRow("SELECT restrict_guild_scout FROM characters WHERE id=$1", s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + row := database.QueryRow("SELECT restrict_guild_scout FROM characters WHERE id=$1", s.CharID) var currentStatus bool - err := row.Scan(¤tStatus) + err = row.Scan(¤tStatus) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to retrieve character guild scout status", zap.Error(err), - zap.Uint32("charID", s.charID), + zap.Uint32("charID", s.CharID), ) - doAckSimpleFail(s, pkt.AckHandle, nil) + DoAckSimpleFail(s, pkt.AckHandle, nil) return } @@ -290,23 +300,26 @@ func handleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { response = 0x01 } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, response}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, response}) } -func handleMsgMhfSetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfSetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSetRejectGuildScout) - - _, err := s.server.db.Exec("UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2", pkt.Reject, s.charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec("UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2", pkt.Reject, s.CharID) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to update character guild scout status", zap.Error(err), - zap.Uint32("charID", s.charID), + zap.Uint32("charID", s.CharID), ) - doAckSimpleFail(s, pkt.AckHandle, nil) + DoAckSimpleFail(s, pkt.AckHandle, nil) return } - doAckSimpleSucceed(s, pkt.AckHandle, nil) + DoAckSimpleSucceed(s, pkt.AckHandle, nil) } diff --git a/server/channelserver/handlers_guild_tresure.go b/server/channelserver/handlers_guild_tresure.go index 9c2a0875a..3c12a76cd 100644 --- a/server/channelserver/handlers_guild_tresure.go +++ b/server/channelserver/handlers_guild_tresure.go @@ -1,10 +1,13 @@ package channelserver import ( + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/stringsupport" + "fmt" "time" ) @@ -21,24 +24,27 @@ type TreasureHunt struct { Claimed bool `db:"claimed"` } -func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil || guild == nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } var hunts []TreasureHunt var hunt TreasureHunt - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch pkt.MaxHunts { case 1: - err = s.server.db.QueryRowx(`SELECT id, host_id, destination, level, start, hunt_data FROM guild_hunts WHERE host_id=$1 AND acquired=FALSE`, s.charID).StructScan(&hunt) + err = database.QueryRowx(`SELECT id, host_id, destination, level, start, hunt_data FROM guild_hunts WHERE host_id=$1 AND acquired=FALSE`, s.CharID).StructScan(&hunt) if err == nil { hunts = append(hunts, hunt) } case 30: - rows, err := s.server.db.Queryx(`SELECT gh.id, gh.host_id, gh.destination, gh.level, gh.start, gh.collected, gh.hunt_data, + rows, err := database.Queryx(`SELECT gh.id, gh.host_id, gh.destination, gh.level, gh.start, gh.collected, gh.hunt_data, (SELECT COUNT(*) FROM guild_characters gc WHERE gc.treasure_hunt = gh.id AND gc.character_id <> $1) AS hunters, CASE WHEN ghc.character_id IS NOT NULL THEN true @@ -47,15 +53,15 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { FROM guild_hunts gh LEFT JOIN guild_hunts_claimed ghc ON gh.id = ghc.hunt_id AND ghc.character_id = $1 WHERE gh.guild_id=$2 AND gh.level=2 AND gh.acquired=TRUE - `, s.charID, guild.ID) + `, s.CharID, guild.ID) if err != nil { rows.Close() - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } else { for rows.Next() { err = rows.StructScan(&hunt) - if err == nil && hunt.Start.Add(time.Second*time.Duration(s.server.erupeConfig.GameplayOptions.TreasureHuntExpiry)).After(gametime.TimeAdjusted()) { + if err == nil && hunt.Start.Add(time.Second*time.Duration(config.GetConfig().GameplayOptions.TreasureHuntExpiry)).After(gametime.TimeAdjusted()) { hunts = append(hunts, hunt) } } @@ -77,22 +83,22 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { bf.WriteBool(h.Claimed) bf.WriteBytes(h.HuntData) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegistGuildTresure) bf := byteframe.NewByteFrameFromBytes(pkt.Data) huntData := byteframe.NewByteFrame() - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil || guild == nil { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } guildCats := getGuildAirouList(s) destination := bf.ReadUint32() level := bf.ReadUint32() - huntData.WriteUint32(s.charID) + huntData.WriteUint32(s.CharID) huntData.WriteBytes(stringsupport.PaddedString(s.Name, 18, true)) catsUsed := "" for i := 0; i < 5; i++ { @@ -109,29 +115,41 @@ func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) { huntData.WriteBytes(bf.ReadBytes(9)) } } - s.server.db.Exec(`INSERT INTO guild_hunts (guild_id, host_id, destination, level, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6) - `, guild.ID, s.charID, destination, level, huntData.Data(), catsUsed) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`INSERT INTO guild_hunts (guild_id, host_id, destination, level, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6) + `, guild.ID, s.CharID, destination, level, huntData.Data(), catsUsed) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure) - s.server.db.Exec(`UPDATE guild_hunts SET acquired=true WHERE id=$1`, pkt.HuntID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE guild_hunts SET acquired=true WHERE id=$1`, pkt.HuntID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } -func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperateGuildTresureReport) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch pkt.State { case 0: // Report registration - s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=$1 WHERE character_id=$2`, pkt.HuntID, s.charID) + database.Exec(`UPDATE guild_characters SET treasure_hunt=$1 WHERE character_id=$2`, pkt.HuntID, s.CharID) case 1: // Collected by hunter - s.server.db.Exec(`UPDATE guild_hunts SET collected=true WHERE id=$1`, pkt.HuntID) - s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE treasure_hunt=$1`, pkt.HuntID) + database.Exec(`UPDATE guild_hunts SET collected=true WHERE id=$1`, pkt.HuntID) + database.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE treasure_hunt=$1`, pkt.HuntID) case 2: // Claim treasure - s.server.db.Exec(`INSERT INTO guild_hunts_claimed VALUES ($1, $2)`, pkt.HuntID, s.charID) + database.Exec(`INSERT INTO guild_hunts_claimed VALUES ($1, $2)`, pkt.HuntID, s.CharID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type TreasureSouvenir struct { @@ -139,7 +157,7 @@ type TreasureSouvenir struct { Quantity uint32 } -func handleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGuildTresureSouvenir) bf := byteframe.NewByteFrame() bf.WriteUint32(0) @@ -149,10 +167,10 @@ func handleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(souvenir.Destination) bf.WriteUint32(souvenir.Quantity) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } -func handleMsgMhfAcquireGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) { +func HandleMsgMhfAcquireGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresureSouvenir) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_house.go b/server/channelserver/handlers_house.go index 692fca4a3..f10d5301f 100644 --- a/server/channelserver/handlers_house.go +++ b/server/channelserver/handlers_house.go @@ -1,9 +1,10 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/mhfitem" ps "erupe-ce/utils/pascalstring" "erupe-ce/utils/stringsupport" @@ -42,8 +43,12 @@ FROM warehouse func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateInterior) - s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type HouseData struct { @@ -57,6 +62,10 @@ type HouseData struct { func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateHouse) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() bf.WriteUint16(0) var houses []HouseData @@ -65,18 +74,18 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { switch pkt.Method { case 1: var friendsList string - s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&friendsList) + database.QueryRow("SELECT friends FROM characters WHERE id=$1", s.CharID).Scan(&friendsList) cids := stringsupport.CSVElems(friendsList) for _, cid := range cids { house := HouseData{} - row := s.server.db.QueryRowx(houseQuery, cid) + row := database.QueryRowx(houseQuery, cid) err := row.StructScan(&house) if err == nil { houses = append(houses, house) } } case 2: - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil || guild == nil { break } @@ -86,7 +95,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { } for _, member := range guildMembers { house := HouseData{} - row := s.server.db.QueryRowx(houseQuery, member.CharID) + row := database.QueryRowx(houseQuery, member.CharID) err = row.StructScan(&house) if err == nil { houses = append(houses, house) @@ -96,7 +105,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { houseQuery = `SELECT c.id, hr, gr, name, COALESCE(ub.house_state, 2) as house_state, COALESCE(ub.house_password, '') as house_password FROM characters c LEFT JOIN user_binary ub ON ub.id = c.id WHERE name ILIKE $1` house := HouseData{} - rows, _ := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name)) + rows, _ := database.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name)) for rows.Next() { err := rows.StructScan(&house) if err == nil { @@ -105,7 +114,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { } case 4: house := HouseData{} - row := s.server.db.QueryRowx(houseQuery, pkt.CharID) + row := database.QueryRowx(houseQuery, pkt.CharID) err := row.StructScan(&house) if err == nil { houses = append(houses, house) @@ -122,39 +131,47 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(0) } bf.WriteUint16(house.HR) - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { bf.WriteUint16(house.GR) } ps.Uint8(bf, house.Name, true) } bf.Seek(0, 0) bf.WriteUint16(uint16(len(houses))) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateHouse) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } // 01 = closed // 02 = open anyone // 03 = open friends // 04 = open guild // 05 = open friends+guild - s.server.db.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadHouse) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() var state uint8 var password string - s.server.db.QueryRow(`SELECT COALESCE(house_state, 2) as house_state, COALESCE(house_password, '') as house_password FROM user_binary WHERE id=$1 + database.QueryRow(`SELECT COALESCE(house_state, 2) as house_state, COALESCE(house_password, '') as house_password FROM user_binary WHERE id=$1 `, pkt.CharID).Scan(&state, &password) if pkt.Destination != 9 && len(pkt.Password) > 0 && pkt.CheckPass { if pkt.Password != password { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } } @@ -165,10 +182,10 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) { // Friends list verification if state == 3 || state == 5 { var friendsList string - s.server.db.QueryRow(`SELECT friends FROM characters WHERE id=$1`, pkt.CharID).Scan(&friendsList) + database.QueryRow(`SELECT friends FROM characters WHERE id=$1`, pkt.CharID).Scan(&friendsList) cids := stringsupport.CSVElems(friendsList) for _, cid := range cids { - if uint32(cid) == s.charID { + if uint32(cid) == s.CharID { allowed = true break } @@ -177,8 +194,8 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) { // Guild verification if state > 3 { - ownGuild, err := GetGuildInfoByCharacterId(s, s.charID) - isApplicant, _ := ownGuild.HasApplicationForCharID(s, s.charID) + ownGuild, err := GetGuildInfoByCharacterId(s, s.CharID) + isApplicant, _ := ownGuild.HasApplicationForCharID(s, s.CharID) if err == nil && ownGuild != nil { othersGuild, err := GetGuildInfoByCharacterId(s, pkt.CharID) if err == nil && othersGuild != nil { @@ -190,13 +207,13 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) { } if !allowed { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } } var houseTier, houseData, houseFurniture, bookshelf, gallery, tore, garden []byte - s.server.db.QueryRow(`SELECT house_tier, house_data, house_furniture, bookshelf, gallery, tore, garden FROM user_binary WHERE id=$1 + database.QueryRow(`SELECT house_tier, house_data, house_furniture, bookshelf, gallery, tore, garden FROM user_binary WHERE id=$1 `, pkt.CharID).Scan(&houseTier, &houseData, &houseFurniture, &bookshelf, &gallery, &tore, &garden) if houseFurniture == nil { houseFurniture = make([]byte, 20) @@ -226,59 +243,76 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) { } } if len(bf.Data()) == 0 { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } else { - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } } func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetMyhouseInfo) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var data []byte - s.server.db.QueryRow(`SELECT mission FROM user_binary WHERE id=$1`, s.charID).Scan(&data) + database.QueryRow(`SELECT mission FROM user_binary WHERE id=$1`, s.CharID).Scan(&data) if len(data) > 0 { - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } else { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 9)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 9)) } } func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo) - s.server.db.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadDecoMyset) - var data []byte - err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&data) + + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load decomyset", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var data []byte + err = database.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.CharID).Scan(&data) + if err != nil { + s.Logger.Error("Failed to load decomyset", zap.Error(err)) } if len(data) == 0 { data = []byte{0x01, 0x00} - if s.server.erupeConfig.ClientID < _config.G10 { + if config.GetConfig().ClientID < config.G10 { data = []byte{0x00, 0x00} } } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveDecoMyset) - var temp []byte - err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&temp) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load decomyset", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var temp []byte + err = database.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.CharID).Scan(&temp) + if err != nil { + s.Logger.Error("Failed to load decomyset", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } // Version handling bf := byteframe.NewByteFrame() var size uint - if s.server.erupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { size = 76 bf.WriteUint8(1) } else { @@ -314,8 +348,8 @@ func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) { } dumpSaveData(s, bf.Data(), "decomyset") - s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type Title struct { @@ -326,13 +360,17 @@ type Title struct { func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateTitle) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var count uint16 bf := byteframe.NewByteFrame() bf.WriteUint16(0) bf.WriteUint16(0) // Unk - rows, err := s.server.db.Queryx("SELECT id, unlocked_at, updated_at FROM titles WHERE char_id=$1", s.charID) + rows, err := database.Queryx("SELECT id, unlocked_at, updated_at FROM titles WHERE char_id=$1", s.CharID) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) return } for rows.Next() { @@ -349,35 +387,47 @@ func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) { } bf.Seek(0, io.SeekStart) bf.WriteUint16(count) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfAcquireTitle(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireTitle) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } for _, title := range pkt.TitleIDs { var exists int - err := s.server.db.QueryRow(`SELECT count(*) FROM titles WHERE id=$1 AND char_id=$2`, title, s.charID).Scan(&exists) + err := database.QueryRow(`SELECT count(*) FROM titles WHERE id=$1 AND char_id=$2`, title, s.CharID).Scan(&exists) if err != nil || exists == 0 { - s.server.db.Exec(`INSERT INTO titles VALUES ($1, $2, now(), now())`, title, s.charID) + database.Exec(`INSERT INTO titles VALUES ($1, $2, now(), now())`, title, s.CharID) } else { - s.server.db.Exec(`UPDATE titles SET updated_at=now() WHERE id=$1 AND char_id=$2`, title, s.charID) + database.Exec(`UPDATE titles SET updated_at=now() WHERE id=$1 AND char_id=$2`, title, s.CharID) } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfResetTitle(s *Session, p mhfpacket.MHFPacket) {} func initializeWarehouse(s *Session) { - var t int - err := s.server.db.QueryRow("SELECT character_id FROM warehouse WHERE character_id=$1", s.charID).Scan(&t) + database, err := db.GetDB() if err != nil { - s.server.db.Exec("INSERT INTO warehouse (character_id) VALUES ($1)", s.charID) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var t int + err = database.QueryRow("SELECT character_id FROM warehouse WHERE character_id=$1", s.CharID).Scan(&t) + if err != nil { + database.Exec("INSERT INTO warehouse (character_id) VALUES ($1)", s.CharID) } } func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOperateWarehouse) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } initializeWarehouse(s) bf := byteframe.NewByteFrame() bf.WriteUint8(pkt.Operation) @@ -386,7 +436,7 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) { var count uint8 itemNames := make([]string, 10) equipNames := make([]string, 10) - s.server.db.QueryRow(fmt.Sprintf("%s WHERE character_id=$1", warehouseNamesQuery), s.charID).Scan(&itemNames[0], + database.QueryRow(fmt.Sprintf("%s WHERE character_id=$1", warehouseNamesQuery), s.CharID).Scan(&itemNames[0], &itemNames[1], &itemNames[2], &itemNames[3], &itemNames[4], &itemNames[5], &itemNames[6], &itemNames[7], &itemNames[8], &itemNames[9], &equipNames[0], &equipNames[1], &equipNames[2], &equipNames[3], &equipNames[4], &equipNames[5], &equipNames[6], &equipNames[7], &equipNames[8], &equipNames[9]) bf.WriteUint32(0) @@ -415,9 +465,9 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) { case 2: switch pkt.BoxType { case 0: - s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID) + database.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.CharID) case 1: - s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID) + database.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.CharID) } case 3: bf.WriteUint32(0) // Usage renewal time, >1 = disabled @@ -433,28 +483,40 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) { // 2 = Rename // 3 = Get usage limit // 4 = Get gift box names (doesn't do anything?) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func addWarehouseItem(s *Session, item mhfitem.MHFItemStack) { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } giftBox := warehouseGetItems(s, 10) item.WarehouseID = token.RNG.Uint32() giftBox = append(giftBox, item) - s.server.db.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.charID) + database.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.CharID) } func addWarehouseEquipment(s *Session, equipment mhfitem.MHFEquipment) { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } giftBox := warehouseGetEquipment(s, 10) equipment.WarehouseID = token.RNG.Uint32() giftBox = append(giftBox, equipment) - s.server.db.Exec("UPDATE warehouse SET equip10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseEquipment(giftBox), s.charID) + database.Exec("UPDATE warehouse SET equip10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseEquipment(giftBox), s.CharID) } func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } initializeWarehouse(s) var data []byte var items []mhfitem.MHFItemStack - s.server.db.QueryRow(fmt.Sprintf(`SELECT item%d FROM warehouse WHERE character_id=$1`, index), s.charID).Scan(&data) + database.QueryRow(fmt.Sprintf(`SELECT item%d FROM warehouse WHERE character_id=$1`, index), s.CharID).Scan(&data) if len(data) > 0 { box := byteframe.NewByteFrameFromBytes(data) numStacks := box.ReadUint16() @@ -467,9 +529,13 @@ func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack { } func warehouseGetEquipment(s *Session, index uint8) []mhfitem.MHFEquipment { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var data []byte var equipment []mhfitem.MHFEquipment - s.server.db.QueryRow(fmt.Sprintf(`SELECT equip%d FROM warehouse WHERE character_id=$1`, index), s.charID).Scan(&data) + database.QueryRow(fmt.Sprintf(`SELECT equip%d FROM warehouse WHERE character_id=$1`, index), s.CharID).Scan(&data) if len(data) > 0 { box := byteframe.NewByteFrameFromBytes(data) numStacks := box.ReadUint16() @@ -493,18 +559,22 @@ func handleMsgMhfEnumerateWarehouse(s *Session, p mhfpacket.MHFPacket) { bf.WriteBytes(mhfitem.SerializeWarehouseEquipment(equipment)) } if bf.Index() > 0 { - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } else { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) } } func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateWarehouse) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch pkt.BoxType { case 0: newStacks := mhfitem.DiffItemStacks(warehouseGetItems(s, pkt.BoxIndex), pkt.UpdatedItems) - s.server.db.Exec(fmt.Sprintf(`UPDATE warehouse SET item%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseItems(newStacks), s.charID) + database.Exec(fmt.Sprintf(`UPDATE warehouse SET item%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseItems(newStacks), s.CharID) case 1: var fEquip []mhfitem.MHFEquipment oEquips := warehouseGetEquipment(s, pkt.BoxIndex) @@ -528,7 +598,7 @@ func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) { fEquip = append(fEquip, oEquip) } } - s.server.db.Exec(fmt.Sprintf(`UPDATE warehouse SET equip%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseEquipment(fEquip), s.charID) + database.Exec(fmt.Sprintf(`UPDATE warehouse SET equip%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseEquipment(fEquip), s.CharID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_kouryou.go b/server/channelserver/handlers_kouryou.go index 7487a017e..1f2e23d36 100644 --- a/server/channelserver/handlers_kouryou.go +++ b/server/channelserver/handlers_kouryou.go @@ -3,6 +3,8 @@ package channelserver import ( "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" + "fmt" "go.uber.org/zap" ) @@ -10,37 +12,49 @@ import ( func handleMsgMhfAddKouryouPoint(s *Session, p mhfpacket.MHFPacket) { // hunting with both ranks maxed gets you these pkt := p.(*mhfpacket.MsgMhfAddKouryouPoint) - var points int - err := s.server.db.QueryRow("UPDATE characters SET kouryou_point=COALESCE(kouryou_point + $1, $1) WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.charID).Scan(&points) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to update KouryouPoint in db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var points int + err = database.QueryRow("UPDATE characters SET kouryou_point=COALESCE(kouryou_point + $1, $1) WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.CharID).Scan(&points) + if err != nil { + s.Logger.Error("Failed to update KouryouPoint in db", zap.Error(err)) } resp := byteframe.NewByteFrame() resp.WriteUint32(uint32(points)) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfGetKouryouPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetKouryouPoint) - var points int - err := s.server.db.QueryRow("SELECT COALESCE(kouryou_point, 0) FROM characters WHERE id = $1", s.charID).Scan(&points) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to get kouryou_point savedata from db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var points int + err = database.QueryRow("SELECT COALESCE(kouryou_point, 0) FROM characters WHERE id = $1", s.CharID).Scan(&points) + if err != nil { + s.Logger.Error("Failed to get kouryou_point savedata from db", zap.Error(err)) } resp := byteframe.NewByteFrame() resp.WriteUint32(uint32(points)) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfExchangeKouryouPoint(s *Session, p mhfpacket.MHFPacket) { // spent at the guildmaster, 10000 a roll var points int pkt := p.(*mhfpacket.MsgMhfExchangeKouryouPoint) - err := s.server.db.QueryRow("UPDATE characters SET kouryou_point=kouryou_point - $1 WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.charID).Scan(&points) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to update platemyset savedata in db", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("UPDATE characters SET kouryou_point=kouryou_point - $1 WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.CharID).Scan(&points) + if err != nil { + s.Logger.Error("Failed to update platemyset savedata in db", zap.Error(err)) } resp := byteframe.NewByteFrame() resp.WriteUint32(uint32(points)) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } diff --git a/server/channelserver/handlers_mail.go b/server/channelserver/handlers_mail.go index d17dca7b4..3859df53c 100644 --- a/server/channelserver/handlers_mail.go +++ b/server/channelserver/handlers_mail.go @@ -2,7 +2,9 @@ package channelserver import ( "database/sql" + "erupe-ce/utils/db" "erupe-ce/utils/stringsupport" + "fmt" "time" "erupe-ce/network/binpacket" @@ -31,21 +33,23 @@ type Mail struct { } func (m *Mail) Send(s *Session, transaction *sql.Tx) error { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } query := ` INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite, is_sys_message) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ` - var err error - if transaction == nil { - _, err = s.server.db.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage) + _, err = database.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage) } else { _, err = transaction.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage) } if err != nil { - s.logger.Error( + s.Logger.Error( "failed to send mail", zap.Error(err), zap.Uint32("senderID", m.SenderID), @@ -64,12 +68,16 @@ func (m *Mail) Send(s *Session, transaction *sql.Tx) error { } func (m *Mail) MarkRead(s *Session) error { - _, err := s.server.db.Exec(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _, err = database.Exec(` UPDATE mail SET read = true WHERE id = $1 `, m.ID) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to mark mail as read", zap.Error(err), zap.Int("mailID", m.ID), @@ -81,7 +89,11 @@ func (m *Mail) MarkRead(s *Session) error { } func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) { - rows, err := s.server.db.Queryx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(` SELECT m.id, m.sender_id, @@ -105,7 +117,7 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) { `, charID) if err != nil { - s.logger.Error("failed to get mail for character", zap.Error(err), zap.Uint32("charID", charID)) + s.Logger.Error("failed to get mail for character", zap.Error(err), zap.Uint32("charID", charID)) return nil, err } @@ -129,7 +141,11 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) { } func GetMailByID(s *Session, ID int) (*Mail, error) { - row := s.server.db.QueryRowx(` + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + row := database.QueryRowx(` SELECT m.id, m.sender_id, @@ -154,10 +170,10 @@ func GetMailByID(s *Session, ID int) (*Mail, error) { mail := &Mail{} - err := row.StructScan(mail) + err = row.StructScan(mail) if err != nil { - s.logger.Error( + s.Logger.Error( "failed to retrieve mail", zap.Error(err), zap.Int("mailID", ID), @@ -190,11 +206,15 @@ func SendMailNotification(s *Session, m *Mail, recipient *Session) { } func getCharacterName(s *Session, charID uint32) string { - row := s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", charID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + row := database.QueryRow("SELECT name FROM characters WHERE id = $1", charID) charName := "" - err := row.Scan(&charName) + err = row.Scan(&charName) if err != nil { return "" @@ -204,32 +224,35 @@ func getCharacterName(s *Session, charID uint32) string { func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfReadMail) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } mailId := s.mailList[pkt.AccIndex] if mailId == 0 { - doAckBufSucceed(s, pkt.AckHandle, []byte{0}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0}) return } mail, err := GetMailByID(s, mailId) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, []byte{0}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0}) return } - s.server.db.Exec(`UPDATE mail SET read = true WHERE id = $1`, mail.ID) + database.Exec(`UPDATE mail SET read = true WHERE id = $1`, mail.ID) bf := byteframe.NewByteFrame() body := stringsupport.UTF8ToSJIS(mail.Body) bf.WriteNullTerminatedBytes(body) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfListMail) - mail, err := GetMailListForCharacter(s, s.charID) + mail, err := GetMailListForCharacter(s, s.CharID) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, []byte{0}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0}) return } @@ -290,64 +313,71 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { } } - doAckBufSucceed(s, pkt.AckHandle, msg.Data()) + DoAckBufSucceed(s, pkt.AckHandle, msg.Data()) } func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfOprtMail) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } mail, err := GetMailByID(s, s.mailList[pkt.AccIndex]) if err != nil { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } switch pkt.Operation { case mhfpacket.OperateMailDelete: - s.server.db.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, mail.ID) + database.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, mail.ID) case mhfpacket.OperateMailLock: - s.server.db.Exec(`UPDATE mail SET locked = TRUE WHERE id = $1`, mail.ID) + database.Exec(`UPDATE mail SET locked = TRUE WHERE id = $1`, mail.ID) case mhfpacket.OperateMailUnlock: - s.server.db.Exec(`UPDATE mail SET locked = FALSE WHERE id = $1`, mail.ID) + database.Exec(`UPDATE mail SET locked = FALSE WHERE id = $1`, mail.ID) case mhfpacket.OperateMailAcquireItem: - s.server.db.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, mail.ID) + database.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, mail.ID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfSendMail(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSendMail) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } query := ` INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite) VALUES ($1, $2, $3, $4, $5, $6, $7) ` if pkt.RecipientID == 0 { // Guild mail - g, err := GetGuildInfoByCharacterId(s, s.charID) + g, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil { - s.logger.Error("Failed to get guild info for mail") - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to get guild info for mail") + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } gm, err := GetGuildMembers(s, g.ID, false) if err != nil { - s.logger.Error("Failed to get guild members for mail") - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to get guild members for mail") + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } for i := 0; i < len(gm); i++ { - _, err := s.server.db.Exec(query, s.charID, gm[i].CharID, pkt.Subject, pkt.Body, 0, 0, false) + _, err := database.Exec(query, s.CharID, gm[i].CharID, pkt.Subject, pkt.Body, 0, 0, false) if err != nil { - s.logger.Error("Failed to send mail") - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to send mail") + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } } } else { - _, err := s.server.db.Exec(query, s.charID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false) + _, err := database.Exec(query, s.CharID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false) if err != nil { - s.logger.Error("Failed to send mail") + s.Logger.Error("Failed to send mail") } } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_mercenary.go b/server/channelserver/handlers_mercenary.go index fe23ea4db..c34865720 100644 --- a/server/channelserver/handlers_mercenary.go +++ b/server/channelserver/handlers_mercenary.go @@ -1,13 +1,16 @@ package channelserver import ( - _config "erupe-ce/config" + config "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/server/channelserver/compression/deltacomp" "erupe-ce/server/channelserver/compression/nullcomp" + "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/stringsupport" + "fmt" "io" "time" @@ -17,22 +20,30 @@ import ( func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadPartner) var data []byte - err := s.server.db.QueryRow("SELECT partner FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT partner FROM characters WHERE id = $1", s.CharID).Scan(&data) if len(data) == 0 { - s.logger.Error("Failed to load partner", zap.Error(err)) + s.Logger.Error("Failed to load partner", zap.Error(err)) data = make([]byte, 9) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSavePartner) - dumpSaveData(s, pkt.RawDataPayload, "partner") - _, err := s.server.db.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to save partner", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + dumpSaveData(s, pkt.RawDataPayload, "partner") + _, err = database.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) + if err != nil { + s.Logger.Error("Failed to save partner", zap.Error(err)) + } + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) { @@ -51,36 +62,44 @@ func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(dispatch.Unk) bf.WriteUint32(dispatch.Timestamp) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi) naviLength := 552 - if s.server.erupeConfig.ClientID <= _config.G7 { + if config.GetConfig().ClientID <= config.G7 { naviLength = 280 } var data []byte - err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.CharID).Scan(&data) if len(data) == 0 { - s.logger.Error("Failed to load hunternavi", zap.Error(err)) + s.Logger.Error("Failed to load hunternavi", zap.Error(err)) data = make([]byte, naviLength) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.IsDataDiff { naviLength := 552 - if s.server.erupeConfig.ClientID <= _config.G7 { + if config.GetConfig().ClientID <= config.G7 { naviLength = 280 } var data []byte // Load existing save - err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) + err := database.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.CharID).Scan(&data) if err != nil { - s.logger.Error("Failed to load hunternavi", zap.Error(err)) + s.Logger.Error("Failed to load hunternavi", zap.Error(err)) } // Check if we actually had any hunternavi data, using a blank buffer if not. @@ -90,22 +109,22 @@ func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { } // Perform diff and compress it to write back to db - s.logger.Info("Diffing...") + s.Logger.Info("Diffing...") saveOutput := deltacomp.ApplyDataDiff(pkt.RawDataPayload, data) - _, err = s.server.db.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", saveOutput, s.charID) + _, err = database.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", saveOutput, s.CharID) if err != nil { - s.logger.Error("Failed to save hunternavi", zap.Error(err)) + s.Logger.Error("Failed to save hunternavi", zap.Error(err)) } - s.logger.Info("Wrote recompressed hunternavi back to DB") + s.Logger.Info("Wrote recompressed hunternavi back to DB") } else { dumpSaveData(s, pkt.RawDataPayload, "hunternavi") // simply update database, no extra processing - _, err := s.server.db.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + _, err := database.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) if err != nil { - s.logger.Error("Failed to save hunternavi", zap.Error(err)) + s.Logger.Error("Failed to save hunternavi", zap.Error(err)) } } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfMercenaryHuntdata(s *Session, p mhfpacket.MHFPacket) { @@ -116,9 +135,9 @@ func handleMsgMhfMercenaryHuntdata(s *Session, p mhfpacket.MHFPacket) { // struct Hunt // uint32 HuntID // uint32 MonID - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) } else { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0)) } } @@ -132,39 +151,51 @@ func handleMsgMhfEnumerateMercenaryLog(s *Session, p mhfpacket.MHFPacket) { // []byte Name (len 18) // uint8 Unk // uint8 Unk - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfCreateMercenary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfCreateMercenary) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() var nextID uint32 - _ = s.server.db.QueryRow("SELECT nextval('rasta_id_seq')").Scan(&nextID) - s.server.db.Exec("UPDATE characters SET rasta_id=$1 WHERE id=$2", nextID, s.charID) + _ = database.QueryRow("SELECT nextval('rasta_id_seq')").Scan(&nextID) + database.Exec("UPDATE characters SET rasta_id=$1 WHERE id=$2", nextID, s.CharID) bf.WriteUint32(nextID) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveMercenary) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } dumpSaveData(s, pkt.MercData, "mercenary") if len(pkt.MercData) > 0 { temp := byteframe.NewByteFrameFromBytes(pkt.MercData) - s.server.db.Exec("UPDATE characters SET savemercenary=$1, rasta_id=$2 WHERE id=$3", pkt.MercData, temp.ReadUint32(), s.charID) + database.Exec("UPDATE characters SET savemercenary=$1, rasta_id=$2 WHERE id=$3", pkt.MercData, temp.ReadUint32(), s.CharID) } - s.server.db.Exec("UPDATE characters SET gcp=$1, pact_id=$2 WHERE id=$3", pkt.GCP, pkt.PactMercID, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + database.Exec("UPDATE characters SET gcp=$1, pact_id=$2 WHERE id=$3", pkt.GCP, pkt.PactMercID, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfReadMercenaryW) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } bf := byteframe.NewByteFrame() var pactID, cid uint32 var name string - s.server.db.QueryRow("SELECT pact_id FROM characters WHERE id=$1", s.charID).Scan(&pactID) + database.QueryRow("SELECT pact_id FROM characters WHERE id=$1", s.CharID).Scan(&pactID) if pactID > 0 { - s.server.db.QueryRow("SELECT name, id FROM characters WHERE rasta_id = $1", pactID).Scan(&name, &cid) + database.QueryRow("SELECT name, id FROM characters WHERE rasta_id = $1", pactID).Scan(&name, &cid) bf.WriteUint8(1) // numLends bf.WriteUint32(pactID) bf.WriteUint32(cid) @@ -179,7 +210,7 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { var loans uint8 temp := byteframe.NewByteFrame() if pkt.Op < 2 { - rows, _ := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID) + rows, _ := database.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.CharID) for rows.Next() { err := rows.Scan(&name, &cid, &pactID) if err != nil { @@ -199,8 +230,8 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { if pkt.Op < 1 { var data []byte var gcp uint32 - s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id=$1", s.charID).Scan(&data) - s.server.db.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id=$1", s.charID).Scan(&gcp) + database.QueryRow("SELECT savemercenary FROM characters WHERE id=$1", s.CharID).Scan(&data) + database.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id=$1", s.CharID).Scan(&gcp) if len(data) == 0 { bf.WriteBool(false) @@ -211,53 +242,69 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(gcp) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfReadMercenaryM) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var data []byte - s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id = $1", pkt.CharID).Scan(&data) + database.QueryRow("SELECT savemercenary FROM characters WHERE id = $1", pkt.CharID).Scan(&data) resp := byteframe.NewByteFrame() if len(data) == 0 { resp.WriteBool(false) } else { resp.WriteBytes(data) } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfContractMercenary) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch pkt.Op { case 0: // Form loan - s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID) + database.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID) case 1: // Cancel lend - s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID) + database.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.CharID) case 2: // Cancel loan - s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", pkt.CID) + database.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", pkt.CID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfLoadOtomoAirou(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadOtomoAirou) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var data []byte - err := s.server.db.QueryRow("SELECT otomoairou FROM characters WHERE id = $1", s.charID).Scan(&data) + err = database.QueryRow("SELECT otomoairou FROM characters WHERE id = $1", s.CharID).Scan(&data) if len(data) == 0 { - s.logger.Error("Failed to load otomoairou", zap.Error(err)) + s.Logger.Error("Failed to load otomoairou", zap.Error(err)) data = make([]byte, 10) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveOtomoAirou) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } dumpSaveData(s, pkt.RawDataPayload, "otomoairou") decomp, err := nullcomp.Decompress(pkt.RawDataPayload[1:]) if err != nil { - s.logger.Error("Failed to decompress airou", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to decompress airou", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } bf := byteframe.NewByteFrameFromBytes(decomp) @@ -270,7 +317,7 @@ func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) { dataLen := bf.ReadUint32() catID := bf.ReadUint32() if catID == 0 { - _ = s.server.db.QueryRow("SELECT nextval('airou_id_seq')").Scan(&catID) + _ = database.QueryRow("SELECT nextval('airou_id_seq')").Scan(&catID) } exists := bf.ReadBool() data := bf.ReadBytes(uint(dataLen) - 5) @@ -287,12 +334,12 @@ func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) { save.WriteUint8(catsExist) comp, err := nullcomp.Compress(save.Data()) if err != nil { - s.logger.Error("Failed to compress airou", zap.Error(err)) + s.Logger.Error("Failed to compress airou", zap.Error(err)) } else { comp = append([]byte{0x01}, comp...) - s.server.db.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", comp, s.charID) + database.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", comp, s.CharID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfEnumerateAiroulist(s *Session, p mhfpacket.MHFPacket) { @@ -311,7 +358,7 @@ func handleMsgMhfEnumerateAiroulist(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint16(cat.WeaponID) resp.WriteUint32(0) // 32 bit unix timestamp, either time at which the cat stops being fatigued or the time at which it started } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } type Airou struct { @@ -326,17 +373,21 @@ type Airou struct { } func getGuildAirouList(s *Session) []Airou { + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var guildCats []Airou bannedCats := make(map[uint32]int) - guild, err := GetGuildInfoByCharacterId(s, s.charID) + guild, err := GetGuildInfoByCharacterId(s, s.CharID) if err != nil { return guildCats } - rows, err := s.server.db.Query(`SELECT cats_used FROM guild_hunts gh + rows, err := database.Query(`SELECT cats_used FROM guild_hunts gh INNER JOIN characters c ON gh.host_id = c.id WHERE c.id=$1 - `, s.charID) + `, s.CharID) if err != nil { - s.logger.Warn("Failed to get recently used airous", zap.Error(err)) + s.Logger.Warn("Failed to get recently used airous", zap.Error(err)) return guildCats } @@ -347,19 +398,19 @@ func getGuildAirouList(s *Session) []Airou { if err != nil { continue } - if startTemp.Add(time.Second * time.Duration(s.server.erupeConfig.GameplayOptions.TreasureHuntPartnyaCooldown)).Before(gametime.TimeAdjusted()) { + if startTemp.Add(time.Second * time.Duration(config.GetConfig().GameplayOptions.TreasureHuntPartnyaCooldown)).Before(gametime.TimeAdjusted()) { for i, j := range stringsupport.CSVElems(csvTemp) { bannedCats[uint32(j)] = i } } } - rows, err = s.server.db.Query(`SELECT c.otomoairou FROM characters c + rows, err = database.Query(`SELECT c.otomoairou FROM characters c INNER JOIN guild_characters gc ON gc.character_id = c.id WHERE gc.guild_id = $1 AND c.otomoairou IS NOT NULL ORDER BY c.id LIMIT 60`, guild.ID) if err != nil { - s.logger.Warn("Selecting otomoairou based on guild failed", zap.Error(err)) + s.Logger.Warn("Selecting otomoairou based on guild failed", zap.Error(err)) return guildCats } @@ -373,7 +424,7 @@ func getGuildAirouList(s *Session) []Airou { if data[0] == 1 { decomp, err := nullcomp.Decompress(data[1:]) if err != nil { - s.logger.Warn("decomp failure", zap.Error(err)) + s.Logger.Warn("decomp failure", zap.Error(err)) continue } bf := byteframe.NewByteFrameFromBytes(decomp) diff --git a/server/channelserver/handlers_object.go b/server/channelserver/handlers_object.go index f4d4c4602..341dcd1da 100644 --- a/server/channelserver/handlers_object.go +++ b/server/channelserver/handlers_object.go @@ -3,6 +3,7 @@ package channelserver import ( "fmt" + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" ) @@ -13,18 +14,18 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) { s.stage.Lock() newObj := &Object{ id: s.NextObjectID(), - ownerCharID: s.charID, + ownerCharID: s.CharID, x: pkt.X, y: pkt.Y, z: pkt.Z, } - s.stage.objects[s.charID] = newObj + s.stage.objects[s.CharID] = newObj s.stage.Unlock() // Response to our requesting client. resp := byteframe.NewByteFrame() resp.WriteUint32(newObj.id) // New local obj handle. - doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) // Duplicate the object creation to all sessions in the same stage. dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{ ObjID: newObj.id, @@ -34,7 +35,7 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) { OwnerCharID: newObj.ownerCharID, } - s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id)) + s.Logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id)) s.stage.BroadcastMHF(dupObjUpdate, s) } @@ -42,11 +43,11 @@ func handleMsgSysDeleteObject(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysPositionObject(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysPositionObject) - if s.server.erupeConfig.DebugOptions.LogInboundMessages { + if config.GetConfig().DebugOptions.LogInboundMessages { fmt.Printf("[%s] with objectID [%d] move to (%f,%f,%f)\n\n", s.Name, pkt.ObjID, pkt.X, pkt.Y, pkt.Z) } s.stage.Lock() - object, ok := s.stage.objects[s.charID] + object, ok := s.stage.objects[s.CharID] if ok { object.x = pkt.X object.y = pkt.Y @@ -64,16 +65,16 @@ func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) { _ = p.(*mhfpacket.MsgSysSetObjectBinary) /* This causes issues with PS3 as this actually sends with endiness! - for _, session := range s.server.sessions { - if session.charID == s.charID { - s.server.userBinaryPartsLock.Lock() - s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: 3}] = pkt.RawDataPayload - s.server.userBinaryPartsLock.Unlock() + for _, session := range s.Server.sessions { + if session.CharID == s.CharID { + s.Server.userBinaryPartsLock.Lock() + s.Server.userBinaryParts[userBinaryPartID{charID: s.CharID, index: 3}] = pkt.RawDataPayload + s.Server.userBinaryPartsLock.Unlock() msg := &mhfpacket.MsgSysNotifyUserBinary{ - CharID: s.charID, + CharID: s.CharID, BinaryType: 3, } - s.server.BroadcastMHF(msg, s) + s.Server.BroadcastMHF(msg, s) } } */ diff --git a/server/channelserver/handlers_plate.go b/server/channelserver/handlers_plate.go index 19fdd84a2..95392b95c 100644 --- a/server/channelserver/handlers_plate.go +++ b/server/channelserver/handlers_plate.go @@ -4,40 +4,50 @@ import ( "erupe-ce/network/mhfpacket" "erupe-ce/server/channelserver/compression/deltacomp" "erupe-ce/server/channelserver/compression/nullcomp" + "erupe-ce/utils/db" + "fmt" + "go.uber.org/zap" ) func handleMsgMhfLoadPlateData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadPlateData) var data []byte - err := s.server.db.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load platedata", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckBufSucceed(s, pkt.AckHandle, data) + err = database.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.CharID).Scan(&data) + if err != nil { + s.Logger.Error("Failed to load platedata", zap.Error(err)) + } + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSavePlateData) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.IsDataDiff { var data []byte // Load existing save - err := s.server.db.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.charID).Scan(&data) + err := database.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.CharID).Scan(&data) if err != nil { - s.logger.Error("Failed to load platedata", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to load platedata", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } if len(data) > 0 { // Decompress - s.logger.Info("Decompressing...") + s.Logger.Info("Decompressing...") data, err = nullcomp.Decompress(data) if err != nil { - s.logger.Error("Failed to decompress platedata", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to decompress platedata", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } } else { @@ -46,66 +56,73 @@ func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) { } // Perform diff and compress it to write back to db - s.logger.Info("Diffing...") + s.Logger.Info("Diffing...") saveOutput, err := nullcomp.Compress(deltacomp.ApplyDataDiff(pkt.RawDataPayload, data)) if err != nil { - s.logger.Error("Failed to diff and compress platedata", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to diff and compress platedata", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } - _, err = s.server.db.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", saveOutput, s.charID) + _, err = database.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", saveOutput, s.CharID) if err != nil { - s.logger.Error("Failed to save platedata", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to save platedata", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } - s.logger.Info("Wrote recompressed platedata back to DB") + s.Logger.Info("Wrote recompressed platedata back to DB") } else { dumpSaveData(s, pkt.RawDataPayload, "platedata") // simply update database, no extra processing - _, err := s.server.db.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + _, err := database.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) if err != nil { - s.logger.Error("Failed to save platedata", zap.Error(err)) + s.Logger.Error("Failed to save platedata", zap.Error(err)) } } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfLoadPlateBox(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadPlateBox) var data []byte - err := s.server.db.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load platebox", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) } - doAckBufSucceed(s, pkt.AckHandle, data) + err = database.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.CharID).Scan(&data) + if err != nil { + s.Logger.Error("Failed to load platebox", zap.Error(err)) + } + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSavePlateBox) - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.IsDataDiff { var data []byte // Load existing save - err := s.server.db.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.charID).Scan(&data) + err := database.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.CharID).Scan(&data) if err != nil { - s.logger.Error("Failed to load platebox", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to load platebox", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } // Decompress if len(data) > 0 { // Decompress - s.logger.Info("Decompressing...") + s.Logger.Info("Decompressing...") data, err = nullcomp.Decompress(data) if err != nil { - s.logger.Error("Failed to decompress platebox", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to decompress platebox", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } } else { @@ -114,51 +131,59 @@ func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) { } // Perform diff and compress it to write back to db - s.logger.Info("Diffing...") + s.Logger.Info("Diffing...") saveOutput, err := nullcomp.Compress(deltacomp.ApplyDataDiff(pkt.RawDataPayload, data)) if err != nil { - s.logger.Error("Failed to diff and compress platebox", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to diff and compress platebox", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } - _, err = s.server.db.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", saveOutput, s.charID) + _, err = database.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", saveOutput, s.CharID) if err != nil { - s.logger.Error("Failed to save platebox", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Logger.Error("Failed to save platebox", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) return } - s.logger.Info("Wrote recompressed platebox back to DB") + s.Logger.Info("Wrote recompressed platebox back to DB") } else { dumpSaveData(s, pkt.RawDataPayload, "platebox") // simply update database, no extra processing - _, err := s.server.db.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + _, err := database.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) if err != nil { - s.logger.Error("Failed to save platebox", zap.Error(err)) + s.Logger.Error("Failed to save platebox", zap.Error(err)) } } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfLoadPlateMyset(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadPlateMyset) var data []byte - err := s.server.db.QueryRow("SELECT platemyset FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT platemyset FROM characters WHERE id = $1", s.CharID).Scan(&data) if len(data) == 0 { - s.logger.Error("Failed to load platemyset", zap.Error(err)) + s.Logger.Error("Failed to load platemyset", zap.Error(err)) data = make([]byte, 1920) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSavePlateMyset(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSavePlateMyset) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } // looks to always return the full thing, simply update database, no extra processing dumpSaveData(s, pkt.RawDataPayload, "platemyset") - _, err := s.server.db.Exec("UPDATE characters SET platemyset=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + _, err = database.Exec("UPDATE characters SET platemyset=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) if err != nil { - s.logger.Error("Failed to save platemyset", zap.Error(err)) + s.Logger.Error("Failed to save platemyset", zap.Error(err)) } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } diff --git a/server/channelserver/handlers_quest.go b/server/channelserver/handlers_quest.go index 0d2412365..6944fbbad 100644 --- a/server/channelserver/handlers_quest.go +++ b/server/channelserver/handlers_quest.go @@ -4,10 +4,11 @@ import ( "database/sql" "encoding/binary" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/decryption" "erupe-ce/utils/gametime" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" ps "erupe-ce/utils/pascalstring" "fmt" @@ -62,16 +63,16 @@ func BackportQuest(data []byte) []byte { } fillLength := uint32(108) - if _config.ErupeConfig.ClientID <= _config.S6 { + if config.GetConfig().ClientID <= config.S6 { fillLength = 44 - } else if _config.ErupeConfig.ClientID <= _config.F5 { + } else if config.GetConfig().ClientID <= config.F5 { fillLength = 52 - } else if _config.ErupeConfig.ClientID <= _config.G101 { + } else if config.GetConfig().ClientID <= config.G101 { fillLength = 76 } copy(data[wp:wp+fillLength], data[rp:rp+fillLength]) - if _config.ErupeConfig.ClientID <= _config.G91 { + if config.GetConfig().ClientID <= config.G91 { patterns := [][]byte{ {0x0A, 0x00, 0x01, 0x33, 0xD7, 0x00}, // 10% Armor Sphere -> Stone {0x06, 0x00, 0x02, 0x33, 0xD8, 0x00}, // 6% Armor Sphere+ -> Iron Ore @@ -94,8 +95,8 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysGetFile) if pkt.IsScenario { - if s.server.erupeConfig.DebugOptions.QuestTools { - s.logger.Debug( + if config.GetConfig().DebugOptions.QuestTools { + s.Logger.Debug( "Scenario", zap.Uint8("CategoryID", pkt.ScenarioIdentifer.CategoryID), zap.Uint32("MainID", pkt.ScenarioIdentifer.MainID), @@ -105,49 +106,49 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) { } filename := fmt.Sprintf("%d_0_0_0_S%d_T%d_C%d", pkt.ScenarioIdentifer.CategoryID, pkt.ScenarioIdentifer.MainID, pkt.ScenarioIdentifer.Flags, pkt.ScenarioIdentifer.ChapterID) // Read the scenario file. - data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("scenarios/%s.bin", filename))) + data, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("scenarios/%s.bin", filename))) if err != nil { - s.logger.Error(fmt.Sprintf("Failed to open file: %s/scenarios/%s.bin", s.server.erupeConfig.BinPath, filename)) + s.Logger.Error(fmt.Sprintf("Failed to open file: %s/scenarios/%s.bin", config.GetConfig().BinPath, filename)) // This will crash the game. - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) return } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } else { - if s.server.erupeConfig.DebugOptions.QuestTools { - s.logger.Debug( + if config.GetConfig().DebugOptions.QuestTools { + s.Logger.Debug( "Quest", zap.String("Filename", pkt.Filename), ) } - if s.server.erupeConfig.GameplayOptions.SeasonOverride { + if config.GetConfig().GameplayOptions.SeasonOverride { pkt.Filename = seasonConversion(s, pkt.Filename) } - data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename))) + data, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename))) if err != nil { - s.logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", s.server.erupeConfig.BinPath, pkt.Filename)) + s.Logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", config.GetConfig().BinPath, pkt.Filename)) // This will crash the game. - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) return } - if _config.ErupeConfig.ClientID <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport { + if config.GetConfig().ClientID <= config.Z1 && config.GetConfig().DebugOptions.AutoQuestBackport { data = BackportQuest(decryption.UnpackSimple(data)) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } } func seasonConversion(s *Session, questFile string) string { - filename := fmt.Sprintf("%s%d", questFile[:6], s.server.Season()) + filename := fmt.Sprintf("%s%d", questFile[:6], s.Server.Season()) // Return the seasonal file - if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", filename))); err == nil { + if _, err := os.Stat(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%s.bin", filename))); err == nil { return filename } else { // Attempt to return the requested quest file if the seasonal file doesn't exist - if _, err = os.Stat(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", questFile))); err == nil { + if _, err = os.Stat(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%s.bin", questFile))); err == nil { return questFile } @@ -169,34 +170,42 @@ func seasonConversion(s *Session, questFile string) string { func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest) var data []byte - err := s.server.db.QueryRow("SELECT savefavoritequest FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT savefavoritequest FROM characters WHERE id = $1", s.CharID).Scan(&data) if err == nil && len(data) > 0 { - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } else { - doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) } } func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest) dumpSaveData(s, pkt.Data, "favquest") - s.server.db.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func loadQuestFile(s *Session, questId int) []byte { - data, exists := s.server.questCacheData[questId] - if exists && s.server.questCacheTime[questId].Add(time.Duration(s.server.erupeConfig.QuestCacheExpiry)*time.Second).After(time.Now()) { + data, exists := s.Server.questCacheData[questId] + if exists && s.Server.questCacheTime[questId].Add(time.Duration(config.GetConfig().QuestCacheExpiry)*time.Second).After(time.Now()) { return data } - file, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%05dd0.bin", questId))) + file, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%05dd0.bin", questId))) if err != nil { return nil } decrypted := decryption.UnpackSimple(file) - if _config.ErupeConfig.ClientID <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport { + if config.GetConfig().ClientID <= config.Z1 && config.GetConfig().DebugOptions.AutoQuestBackport { decrypted = BackportQuest(decrypted) } fileBytes := byteframe.NewByteFrameFromBytes(decrypted) @@ -204,13 +213,13 @@ func loadQuestFile(s *Session, questId int) []byte { fileBytes.Seek(int64(fileBytes.ReadUint32()), 0) bodyLength := 320 - if _config.ErupeConfig.ClientID <= _config.S6 { + if config.GetConfig().ClientID <= config.S6 { bodyLength = 160 - } else if _config.ErupeConfig.ClientID <= _config.F5 { + } else if config.GetConfig().ClientID <= config.F5 { bodyLength = 168 - } else if _config.ErupeConfig.ClientID <= _config.G101 { + } else if config.GetConfig().ClientID <= config.G101 { bodyLength = 192 - } else if _config.ErupeConfig.ClientID <= _config.Z1 { + } else if config.GetConfig().ClientID <= config.Z1 { bodyLength = 224 } @@ -240,8 +249,8 @@ func loadQuestFile(s *Session, questId int) []byte { } questBody.WriteBytes(newStrings.Data()) - s.server.questCacheData[questId] = questBody.Data() - s.server.questCacheTime[questId] = time.Now() + s.Server.questCacheData[questId] = questBody.Data() + s.Server.questCacheTime[questId] = time.Now() return questBody.Data() } @@ -263,15 +272,15 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) { bf.WriteUint8(0) // Unk switch questType { case 16: - bf.WriteUint8(s.server.erupeConfig.GameplayOptions.RegularRavienteMaxPlayers) + bf.WriteUint8(config.GetConfig().GameplayOptions.RegularRavienteMaxPlayers) case 22: - bf.WriteUint8(s.server.erupeConfig.GameplayOptions.ViolentRavienteMaxPlayers) + bf.WriteUint8(config.GetConfig().GameplayOptions.ViolentRavienteMaxPlayers) case 40: - bf.WriteUint8(s.server.erupeConfig.GameplayOptions.BerserkRavienteMaxPlayers) + bf.WriteUint8(config.GetConfig().GameplayOptions.BerserkRavienteMaxPlayers) case 50: - bf.WriteUint8(s.server.erupeConfig.GameplayOptions.ExtremeRavienteMaxPlayers) + bf.WriteUint8(config.GetConfig().GameplayOptions.ExtremeRavienteMaxPlayers) case 51: - bf.WriteUint8(s.server.erupeConfig.GameplayOptions.SmallBerserkRavienteMaxPlayers) + bf.WriteUint8(config.GetConfig().GameplayOptions.SmallBerserkRavienteMaxPlayers) default: bf.WriteUint8(maxPlayers) } @@ -282,7 +291,7 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) { bf.WriteBool(true) } bf.WriteUint16(0) // Unk - if _config.ErupeConfig.ClientID >= _config.G2 { + if config.GetConfig().ClientID >= config.G2 { bf.WriteUint32(mark) } bf.WriteUint16(0) // Unk @@ -295,7 +304,7 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) { bf.Seek(25, 0) flagByte := bf.ReadUint8() bf.Seek(25, 0) - if s.server.erupeConfig.GameplayOptions.SeasonOverride { + if config.GetConfig().GameplayOptions.SeasonOverride { bf.WriteUint8(flagByte & 0b11100000) } else { // Allow for seasons to be specified in database, otherwise use the one in the file. @@ -326,11 +335,14 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { var totalCount, returnedCount uint16 bf := byteframe.NewByteFrame() bf.WriteUint16(0) - - rows, err := s.server.db.Query("SELECT id, COALESCE(max_players, 4) AS max_players, quest_type, quest_id, COALESCE(mark, 0) AS mark, COALESCE(flags, -1), start_time, COALESCE(active_days, 0) AS active_days, COALESCE(inactive_days, 0) AS inactive_days FROM event_quests ORDER BY quest_id") + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Query("SELECT id, COALESCE(max_players, 4) AS max_players, quest_type, quest_id, COALESCE(mark, 0) AS mark, COALESCE(flags, -1), start_time, COALESCE(active_days, 0) AS active_days, COALESCE(inactive_days, 0) AS inactive_days FROM event_quests ORDER BY quest_id") if err == nil { currentTime := time.Now() - tx, _ := s.server.db.Begin() + tx, _ := database.Begin() for rows.Next() { var id, mark uint32 @@ -340,7 +352,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { err = rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDays, &inactiveDays) if err != nil { - s.logger.Error("Failed to scan event quest row", zap.Error(err)) + s.Logger.Error("Failed to scan event quest row", zap.Error(err)) continue } @@ -375,11 +387,11 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { data, err := makeEventQuest(s, rows) if err != nil { - s.logger.Error("Failed to make event quest", zap.Error(err)) + s.Logger.Error("Failed to make event quest", zap.Error(err)) continue } else { if len(data) > 896 || len(data) < 352 { - s.logger.Error("Invalid quest data length", zap.Int("len", len(data))) + s.Logger.Error("Invalid quest data length", zap.Int("len", len(data))) continue } else { totalCount++ @@ -504,54 +516,54 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { {ID: 1180, Value: 5}, } - tuneValues = append(tuneValues, tuneValue{1020, uint16(s.server.erupeConfig.GameplayOptions.GCPMultiplier * 100)}) + tuneValues = append(tuneValues, tuneValue{1020, uint16(config.GetConfig().GameplayOptions.GCPMultiplier * 100)}) - tuneValues = append(tuneValues, tuneValue{1029, uint16(s.server.erupeConfig.GameplayOptions.GUrgentRate * 100)}) + tuneValues = append(tuneValues, tuneValue{1029, uint16(config.GetConfig().GameplayOptions.GUrgentRate * 100)}) - if s.server.erupeConfig.GameplayOptions.DisableHunterNavi { + if config.GetConfig().GameplayOptions.DisableHunterNavi { tuneValues = append(tuneValues, tuneValue{1037, 1}) } - if s.server.erupeConfig.GameplayOptions.EnableKaijiEvent { + if config.GetConfig().GameplayOptions.EnableKaijiEvent { tuneValues = append(tuneValues, tuneValue{1106, 1}) } - if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent { + if config.GetConfig().GameplayOptions.EnableHiganjimaEvent { tuneValues = append(tuneValues, tuneValue{1144, 1}) } - if s.server.erupeConfig.GameplayOptions.EnableNierEvent { + if config.GetConfig().GameplayOptions.EnableNierEvent { tuneValues = append(tuneValues, tuneValue{1153, 1}) } - if s.server.erupeConfig.GameplayOptions.DisableRoad { + if config.GetConfig().GameplayOptions.DisableRoad { tuneValues = append(tuneValues, tuneValue{1155, 1}) } // get_hrp_rate_from_rank - tuneValues = append(tuneValues, getTuneValueRange(3000, uint16(s.server.erupeConfig.GameplayOptions.HRPMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3338, uint16(s.server.erupeConfig.GameplayOptions.HRPMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3000, uint16(config.GetConfig().GameplayOptions.HRPMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3338, uint16(config.GetConfig().GameplayOptions.HRPMultiplierNC*100))...) // get_srp_rate_from_rank - tuneValues = append(tuneValues, getTuneValueRange(3013, uint16(s.server.erupeConfig.GameplayOptions.SRPMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3351, uint16(s.server.erupeConfig.GameplayOptions.SRPMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3013, uint16(config.GetConfig().GameplayOptions.SRPMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3351, uint16(config.GetConfig().GameplayOptions.SRPMultiplierNC*100))...) // get_grp_rate_from_rank - tuneValues = append(tuneValues, getTuneValueRange(3026, uint16(s.server.erupeConfig.GameplayOptions.GRPMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3364, uint16(s.server.erupeConfig.GameplayOptions.GRPMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3026, uint16(config.GetConfig().GameplayOptions.GRPMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3364, uint16(config.GetConfig().GameplayOptions.GRPMultiplierNC*100))...) // get_gsrp_rate_from_rank - tuneValues = append(tuneValues, getTuneValueRange(3039, uint16(s.server.erupeConfig.GameplayOptions.GSRPMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3377, uint16(s.server.erupeConfig.GameplayOptions.GSRPMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3039, uint16(config.GetConfig().GameplayOptions.GSRPMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3377, uint16(config.GetConfig().GameplayOptions.GSRPMultiplierNC*100))...) // get_zeny_rate_from_hrank - tuneValues = append(tuneValues, getTuneValueRange(3052, uint16(s.server.erupeConfig.GameplayOptions.ZennyMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3390, uint16(s.server.erupeConfig.GameplayOptions.ZennyMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3052, uint16(config.GetConfig().GameplayOptions.ZennyMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3390, uint16(config.GetConfig().GameplayOptions.ZennyMultiplierNC*100))...) // get_zeny_rate_from_grank - tuneValues = append(tuneValues, getTuneValueRange(3078, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3416, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3078, uint16(config.GetConfig().GameplayOptions.GZennyMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3416, uint16(config.GetConfig().GameplayOptions.GZennyMultiplierNC*100))...) // get_reward_rate_from_hrank - tuneValues = append(tuneValues, getTuneValueRange(3104, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3442, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3104, uint16(config.GetConfig().GameplayOptions.MaterialMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3442, uint16(config.GetConfig().GameplayOptions.MaterialMultiplierNC*100))...) // get_reward_rate_from_grank - tuneValues = append(tuneValues, getTuneValueRange(3130, uint16(s.server.erupeConfig.GameplayOptions.GMaterialMultiplier*100))...) - tuneValues = append(tuneValues, getTuneValueRange(3468, uint16(s.server.erupeConfig.GameplayOptions.GMaterialMultiplierNC*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3130, uint16(config.GetConfig().GameplayOptions.GMaterialMultiplier*100))...) + tuneValues = append(tuneValues, getTuneValueRange(3468, uint16(config.GetConfig().GameplayOptions.GMaterialMultiplierNC*100))...) // get_lottery_rate_from_hrank tuneValues = append(tuneValues, getTuneValueRange(3156, 0)...) tuneValues = append(tuneValues, getTuneValueRange(3494, 0)...) @@ -559,11 +571,11 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = append(tuneValues, getTuneValueRange(3182, 0)...) tuneValues = append(tuneValues, getTuneValueRange(3520, 0)...) // get_hagi_rate_from_hrank - tuneValues = append(tuneValues, getTuneValueRange(3208, s.server.erupeConfig.GameplayOptions.ExtraCarves)...) - tuneValues = append(tuneValues, getTuneValueRange(3546, s.server.erupeConfig.GameplayOptions.ExtraCarvesNC)...) + tuneValues = append(tuneValues, getTuneValueRange(3208, config.GetConfig().GameplayOptions.ExtraCarves)...) + tuneValues = append(tuneValues, getTuneValueRange(3546, config.GetConfig().GameplayOptions.ExtraCarvesNC)...) // get_hagi_rate_from_grank - tuneValues = append(tuneValues, getTuneValueRange(3234, s.server.erupeConfig.GameplayOptions.GExtraCarves)...) - tuneValues = append(tuneValues, getTuneValueRange(3572, s.server.erupeConfig.GameplayOptions.GExtraCarvesNC)...) + tuneValues = append(tuneValues, getTuneValueRange(3234, config.GetConfig().GameplayOptions.GExtraCarves)...) + tuneValues = append(tuneValues, getTuneValueRange(3572, config.GetConfig().GameplayOptions.GExtraCarvesNC)...) // get_nboost_transcend_rate_from_hrank tuneValues = append(tuneValues, getTuneValueRange(3286, 200)...) tuneValues = append(tuneValues, getTuneValueRange(3312, 300)...) @@ -580,23 +592,23 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { tuneValues = temp tuneLimit := 770 - if _config.ErupeConfig.ClientID <= _config.G1 { + if config.GetConfig().ClientID <= config.G1 { tuneLimit = 256 - } else if _config.ErupeConfig.ClientID <= _config.G3 { + } else if config.GetConfig().ClientID <= config.G3 { tuneLimit = 283 - } else if _config.ErupeConfig.ClientID <= _config.GG { + } else if config.GetConfig().ClientID <= config.GG { tuneLimit = 315 - } else if _config.ErupeConfig.ClientID <= _config.G61 { + } else if config.GetConfig().ClientID <= config.G61 { tuneLimit = 332 - } else if _config.ErupeConfig.ClientID <= _config.G7 { + } else if config.GetConfig().ClientID <= config.G7 { tuneLimit = 339 - } else if _config.ErupeConfig.ClientID <= _config.G81 { + } else if config.GetConfig().ClientID <= config.G81 { tuneLimit = 396 - } else if _config.ErupeConfig.ClientID <= _config.G91 { + } else if config.GetConfig().ClientID <= config.G91 { tuneLimit = 694 - } else if _config.ErupeConfig.ClientID <= _config.G101 { + } else if config.GetConfig().ClientID <= config.G101 { tuneLimit = 704 - } else if _config.ErupeConfig.ClientID <= _config.Z2 { + } else if config.GetConfig().ClientID <= config.Z2 { tuneLimit = 750 } if len(tuneValues) > tuneLimit { @@ -644,7 +656,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { bf.Seek(0, io.SeekStart) bf.WriteUint16(returnedCount) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func getTuneValueRange(start uint16, value uint16) []tuneValue { @@ -682,5 +694,5 @@ func handleMsgMhfGetUdBonusQuestInfo(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint8(q.Unk6) } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } diff --git a/server/channelserver/handlers_register.go b/server/channelserver/handlers_register.go index fd8d0f0b9..d26055d35 100644 --- a/server/channelserver/handlers_register.go +++ b/server/channelserver/handlers_register.go @@ -1,6 +1,7 @@ package channelserver import ( + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" "strings" @@ -10,14 +11,14 @@ func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegisterEvent) bf := byteframe.NewByteFrame() // Some kind of check if there's already a session - if pkt.Unk1 && s.server.getRaviSemaphore() == nil { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + if pkt.Unk1 && s.Server.getRaviSemaphore() == nil { + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } bf.WriteUint8(uint8(pkt.WorldID)) bf.WriteUint8(uint8(pkt.LandID)) - bf.WriteUint16(s.server.raviente.id) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + bf.WriteUint16(s.Server.raviente.id) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfReleaseEvent(s *Session, p mhfpacket.MHFPacket) { @@ -71,23 +72,23 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) { bf = byteframe.NewByteFrame() var _old, _new uint32 - s.server.raviente.Lock() + s.Server.raviente.Lock() for _, update := range raviUpdates { switch update.Op { case 2: - _old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, true) + _old, _new = s.Server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, true) case 13, 14: - _old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, false) + _old, _new = s.Server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, false) } bf.WriteUint8(1) bf.WriteUint8(update.Dest) bf.WriteUint32(_old) bf.WriteUint32(_new) } - s.server.raviente.Unlock() - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + s.Server.raviente.Unlock() + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) - if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente { + if config.GetConfig().GameplayOptions.LowLatencyRaviente { s.notifyRavi() } } @@ -100,31 +101,31 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) { for i := uint8(0); i < pkt.Values; i++ { switch pkt.RegisterID { case 0x40000: - bf.WriteUint32(s.server.raviente.state[i]) + bf.WriteUint32(s.Server.raviente.state[i]) case 0x50000: - bf.WriteUint32(s.server.raviente.support[i]) + bf.WriteUint32(s.Server.raviente.support[i]) case 0x60000: - bf.WriteUint32(s.server.raviente.register[i]) + bf.WriteUint32(s.Server.raviente.register[i]) } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func (s *Session) notifyRavi() { - sema := s.server.getRaviSemaphore() + sema := s.Server.getRaviSemaphore() if sema == nil { return } var temp mhfpacket.MHFPacket for i := 0; i < 3; i++ { temp = &mhfpacket.MsgSysLoadRegister{RegisterID: uint32(0x40000 + i*0x10000)} - if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente { + if config.GetConfig().GameplayOptions.LowLatencyRaviente { for session := range sema.clients { session.QueueSendMHF(temp) } } else { for session := range sema.clients { - if session.charID == s.charID { + if session.CharID == s.CharID { session.QueueSendMHF(temp) } } @@ -132,7 +133,7 @@ func (s *Session) notifyRavi() { } } -func (server *Server) getRaviSemaphore() *Semaphore { +func (server *ChannelServer) getRaviSemaphore() *Semaphore { for _, semaphore := range server.semaphore { if strings.HasPrefix(semaphore.name, "hs_l0") && strings.HasSuffix(semaphore.name, "3") { return semaphore diff --git a/server/channelserver/handlers_rengoku.go b/server/channelserver/handlers_rengoku.go index e784dca77..91ab32ee1 100644 --- a/server/channelserver/handlers_rengoku.go +++ b/server/channelserver/handlers_rengoku.go @@ -1,6 +1,8 @@ package channelserver import ( + "erupe-ce/config" + "erupe-ce/utils/db" ps "erupe-ce/utils/pascalstring" "fmt" "os" @@ -18,11 +20,15 @@ func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) { // saved every floor on road, holds values such as floors progressed, points etc. // can be safely handled by the client pkt := p.(*mhfpacket.MsgMhfSaveRengokuData) - dumpSaveData(s, pkt.RawDataPayload, "rengoku") - _, err := s.server.db.Exec("UPDATE characters SET rengokudata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to save rengokudata", zap.Error(err)) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + dumpSaveData(s, pkt.RawDataPayload, "rengoku") + _, err = database.Exec("UPDATE characters SET rengokudata=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID) + if err != nil { + s.Logger.Error("Failed to save rengokudata", zap.Error(err)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) return } bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) @@ -33,23 +39,27 @@ func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) { maxStageSp := bf.ReadUint32() maxScoreSp := bf.ReadUint32() var t int - err = s.server.db.QueryRow("SELECT character_id FROM rengoku_score WHERE character_id=$1", s.charID).Scan(&t) + err = database.QueryRow("SELECT character_id FROM rengoku_score WHERE character_id=$1", s.CharID).Scan(&t) if err != nil { - s.server.db.Exec("INSERT INTO rengoku_score (character_id) VALUES ($1)", s.charID) + database.Exec("INSERT INTO rengoku_score (character_id) VALUES ($1)", s.CharID) } - s.server.db.Exec("UPDATE rengoku_score SET max_stages_mp=$1, max_points_mp=$2, max_stages_sp=$3, max_points_sp=$4 WHERE character_id=$5", maxStageMp, maxScoreMp, maxStageSp, maxScoreSp, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database.Exec("UPDATE rengoku_score SET max_stages_mp=$1, max_points_mp=$2, max_stages_sp=$3, max_points_sp=$4 WHERE character_id=$5", maxStageMp, maxScoreMp, maxStageSp, maxScoreSp, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfLoadRengokuData) var data []byte - err := s.server.db.QueryRow("SELECT rengokudata FROM characters WHERE id = $1", s.charID).Scan(&data) + database, err := db.GetDB() if err != nil { - s.logger.Error("Failed to load rengokudata", zap.Error(err)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT rengokudata FROM characters WHERE id = $1", s.CharID).Scan(&data) + if err != nil { + s.Logger.Error("Failed to load rengokudata", zap.Error(err)) } if len(data) > 0 { - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } else { resp := byteframe.NewByteFrame() resp.WriteUint32(0) @@ -87,18 +97,18 @@ func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(0) resp.WriteUint32(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } } func handleMsgMhfGetRengokuBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetRengokuBinary) // a (massively out of date) version resides in the game's /dat/ folder or up to date can be pulled from packets - data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "rengoku_data.bin")) + data, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, "rengoku_data.bin")) if err != nil { panic(err) } - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } const rengokuScoreQuery = `, c.name FROM rengoku_score rs @@ -113,15 +123,15 @@ type RengokuScore struct { func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateRengokuRanking) - guild, _ := GetGuildInfoByCharacterId(s, s.charID) - isApplicant, _ := guild.HasApplicationForCharID(s, s.charID) + guild, _ := GetGuildInfoByCharacterId(s, s.CharID) + isApplicant, _ := guild.HasApplicationForCharID(s, s.CharID) if isApplicant { guild = nil } if pkt.Leaderboard == 2 || pkt.Leaderboard == 3 || pkt.Leaderboard == 6 || pkt.Leaderboard == 7 { if guild == nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 11)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 11)) return } } @@ -131,25 +141,28 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) { i := uint32(1) bf := byteframe.NewByteFrame() scoreData := byteframe.NewByteFrame() - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var rows *sqlx.Rows switch pkt.Leaderboard { case 0: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery)) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery)) case 1: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery)) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery)) case 2: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID) case 3: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID) case 4: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery)) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery)) case 5: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery)) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery)) case 6: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID) case 7: - rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID) + rows, _ = database.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID) } for rows.Next() { @@ -177,7 +190,7 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) { } bf.WriteUint8(uint8(i) - 1) bf.WriteBytes(scoreData.Data()) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetRengokuRankingRank(s *Session, p mhfpacket.MHFPacket) { @@ -186,5 +199,5 @@ func handleMsgMhfGetRengokuRankingRank(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() bf.WriteUint32(0) // Max stage overall MP rank bf.WriteUint32(0) // Max RdP overall MP rank - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_reserve.go b/server/channelserver/handlers_reserve.go index 9878a41bd..0b8dee9fb 100644 --- a/server/channelserver/handlers_reserve.go +++ b/server/channelserver/handlers_reserve.go @@ -6,14 +6,14 @@ func handleMsgSysReserve188(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysReserve188) // Left as raw bytes because I couldn't easily find the request or resp parser function in the binary. - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgSysReserve18B(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysReserve18B) // Left as raw bytes because I couldn't easily find the request or resp parser function in the binary. - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x3C}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x3C}) } func handleMsgSysReserve55(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_reward.go b/server/channelserver/handlers_reward.go index 7178edcaa..8d30693cd 100644 --- a/server/channelserver/handlers_reward.go +++ b/server/channelserver/handlers_reward.go @@ -12,21 +12,21 @@ func handleMsgMhfGetAdditionalBeatReward(s *Session, p mhfpacket.MHFPacket) { // Actual response in packet captures are all just giant batches of null bytes // I'm assuming this is because it used to be tied to an actual event and // they never bothered killing off the packet when they made it static - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x104)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x104)) } func handleMsgMhfGetUdRankingRewardList(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdRankingRewardList) // Temporary canned response data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetRewardSong(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetRewardSong) // Temporary canned response data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfUseRewardSong(s *Session, p mhfpacket.MHFPacket) {} @@ -39,7 +39,7 @@ func handleMsgMhfAcquireMonthlyReward(s *Session, p mhfpacket.MHFPacket) { resp := byteframe.NewByteFrame() resp.WriteUint32(0) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfAcceptReadReward(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_seibattle.go b/server/channelserver/handlers_seibattle.go index 711311ae5..fb2d9b324 100644 --- a/server/channelserver/handlers_seibattle.go +++ b/server/channelserver/handlers_seibattle.go @@ -12,7 +12,7 @@ func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } type WeeklySeibatuRankingReward struct { @@ -40,7 +40,7 @@ func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket bf.WriteInt32(reward.Unk5) data = append(data, bf) } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) { @@ -49,7 +49,7 @@ func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteBytes(make([]byte, 32)) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { @@ -65,7 +65,7 @@ func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { resp.WriteUint32(1) } - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) { @@ -75,13 +75,13 @@ func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(0) bf.WriteInt32(0) bf.WriteInt32(0) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel) - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) { @@ -96,11 +96,11 @@ func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(0) bf.WriteBytes(make([]byte, 32)) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + 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()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_semaphore.go b/server/channelserver/handlers_semaphore.go index 054ca4ee1..49fd12024 100644 --- a/server/channelserver/handlers_semaphore.go +++ b/server/channelserver/handlers_semaphore.go @@ -11,39 +11,39 @@ import ( ) func removeSessionFromSemaphore(s *Session) { - s.server.semaphoreLock.Lock() - for _, semaphore := range s.server.semaphore { + s.Server.semaphoreLock.Lock() + for _, semaphore := range s.Server.semaphore { if _, exists := semaphore.clients[s]; exists { delete(semaphore.clients, s) } } - s.server.semaphoreLock.Unlock() + s.Server.semaphoreLock.Unlock() } func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateSemaphore) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d}) } func destructEmptySemaphores(s *Session) { - s.server.semaphoreLock.Lock() - for id, sema := range s.server.semaphore { + s.Server.semaphoreLock.Lock() + for id, sema := range s.Server.semaphore { if len(sema.clients) == 0 { - delete(s.server.semaphore, id) + delete(s.Server.semaphore, id) if strings.HasPrefix(id, "hs_l0") { - s.server.resetRaviente() + s.Server.resetRaviente() } - s.logger.Debug("Destructed semaphore", zap.String("sema.name", id)) + s.Logger.Debug("Destructed semaphore", zap.String("sema.name", id)) } } - s.server.semaphoreLock.Unlock() + s.Server.semaphoreLock.Unlock() } func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysDeleteSemaphore) destructEmptySemaphores(s) - s.server.semaphoreLock.Lock() - for id, sema := range s.server.semaphore { + s.Server.semaphoreLock.Lock() + for id, sema := range s.Server.semaphore { if sema.id == pkt.SemaphoreID { for session := range sema.clients { if s == session { @@ -51,22 +51,22 @@ func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) { } } if len(sema.clients) == 0 { - delete(s.server.semaphore, id) + delete(s.Server.semaphore, id) if strings.HasPrefix(id, "hs_l0") { - s.server.resetRaviente() + s.Server.resetRaviente() } - s.logger.Debug("Destructed semaphore", zap.String("sema.name", id)) + s.Logger.Debug("Destructed semaphore", zap.String("sema.name", id)) } } } - s.server.semaphoreLock.Unlock() + s.Server.semaphoreLock.Unlock() } func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore) SemaphoreID := pkt.SemaphoreID - if s.server.HasSemaphore(s) { + if s.Server.HasSemaphore(s) { s.semaphoreMode = !s.semaphoreMode } if s.semaphoreMode { @@ -75,22 +75,22 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { s.semaphoreID[0]++ } - newSemaphore, exists := s.server.semaphore[SemaphoreID] + newSemaphore, exists := s.Server.semaphore[SemaphoreID] if !exists { - s.server.semaphoreLock.Lock() + s.Server.semaphoreLock.Lock() if strings.HasPrefix(SemaphoreID, "hs_l0") { suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:]) - s.server.semaphore[SemaphoreID] = &Semaphore{ + s.Server.semaphore[SemaphoreID] = &Semaphore{ name: pkt.SemaphoreID, id: uint32((suffix + 1) * 0x10000), clients: make(map[*Session]uint32), maxPlayers: 127, } } else { - s.server.semaphore[SemaphoreID] = NewSemaphore(s, SemaphoreID, 1) + s.Server.semaphore[SemaphoreID] = NewSemaphore(s, SemaphoreID, 1) } - newSemaphore = s.server.semaphore[SemaphoreID] - s.server.semaphoreLock.Unlock() + newSemaphore = s.Server.semaphore[SemaphoreID] + s.Server.semaphoreLock.Unlock() } newSemaphore.Lock() @@ -99,7 +99,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { if _, exists := newSemaphore.clients[s]; exists { bf.WriteUint32(newSemaphore.id) } else if uint16(len(newSemaphore.clients)) < newSemaphore.maxPlayers { - newSemaphore.clients[s] = s.charID + newSemaphore.clients[s] = s.CharID s.Lock() s.semaphore = newSemaphore s.Unlock() @@ -107,18 +107,18 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { } else { bf.WriteUint32(0) } - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysAcquireSemaphore) - if sema, exists := s.server.semaphore[pkt.SemaphoreID]; exists { + if sema, exists := s.Server.semaphore[pkt.SemaphoreID]; exists { sema.host = s bf := byteframe.NewByteFrame() bf.WriteUint32(sema.id) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } else { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } } @@ -129,10 +129,10 @@ func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCheckSemaphore) resp := []byte{0x00, 0x00, 0x00, 0x00} - s.server.semaphoreLock.Lock() - if _, exists := s.server.semaphore[pkt.SemaphoreID]; exists { + s.Server.semaphoreLock.Lock() + if _, exists := s.Server.semaphore[pkt.SemaphoreID]; exists { resp = []byte{0x00, 0x00, 0x00, 0x01} } - s.server.semaphoreLock.Unlock() - doAckSimpleSucceed(s, pkt.AckHandle, resp) + s.Server.semaphoreLock.Unlock() + DoAckSimpleSucceed(s, pkt.AckHandle, resp) } diff --git a/server/channelserver/handlers_shop_gacha.go b/server/channelserver/handlers_shop_gacha.go index 334c92593..ba06948fa 100644 --- a/server/channelserver/handlers_shop_gacha.go +++ b/server/channelserver/handlers_shop_gacha.go @@ -1,11 +1,13 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" ps "erupe-ce/utils/pascalstring" + "fmt" "math/rand" ) @@ -62,7 +64,7 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) { bf.WriteUint16(uint16(len(items))) bf.WriteUint16(uint16(len(items))) for _, item := range items { - if _config.ErupeConfig.ClientID >= _config.Z2 { + if config.GetConfig().ClientID >= config.Z2 { bf.WriteUint32(item.ID) } bf.WriteUint32(item.ItemID) @@ -70,19 +72,19 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) { bf.WriteUint16(item.Quantity) bf.WriteUint16(item.MinHR) bf.WriteUint16(item.MinSR) - if _config.ErupeConfig.ClientID >= _config.Z2 { + if config.GetConfig().ClientID >= config.Z2 { bf.WriteUint16(item.MinGR) } bf.WriteUint8(0) // Unk bf.WriteUint8(item.StoreLevel) - if _config.ErupeConfig.ClientID >= _config.Z2 { + if config.GetConfig().ClientID >= config.Z2 { bf.WriteUint16(item.MaxQuantity) bf.WriteUint16(item.UsedQuantity) } - if _config.ErupeConfig.ClientID == _config.Z1 { + if config.GetConfig().ClientID == config.Z1 { bf.WriteUint8(uint8(item.RoadFloors)) bf.WriteUint8(uint8(item.RoadFatalis)) - } else if _config.ErupeConfig.ClientID >= _config.Z2 { + } else if config.GetConfig().ClientID >= config.Z2 { bf.WriteUint16(item.RoadFloors) bf.WriteUint16(item.RoadFatalis) } @@ -92,10 +94,14 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) { func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem { var items []ShopItem var temp ShopItem - rows, err := s.server.db.Queryx(`SELECT id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(`SELECT id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity, COALESCE((SELECT bought FROM shop_items_bought WHERE shop_item_id=si.id AND character_id=$3), 0) as used_quantity, road_floors, road_fatalis FROM shop_items si WHERE shop_type=$1 AND shop_id=$2 - `, shopType, shopID, s.charID) + `, shopType, shopID, s.CharID) if err == nil { for rows.Next() { err = rows.StructScan(&temp) @@ -110,6 +116,10 @@ func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem { func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEnumerateShop) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } // Generic Shop IDs // 0: basic item // 1: gatherables @@ -123,14 +133,14 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { switch pkt.ShopType { case 1: // Running gachas // Fundamentally, gacha works completely differently, just hide it for now. - if _config.ErupeConfig.ClientID <= _config.G7 { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + if config.GetConfig().ClientID <= config.G7 { + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } - rows, err := s.server.db.Queryx("SELECT id, min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden FROM gacha_shop") + rows, err := database.Queryx("SELECT id, min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden FROM gacha_shop") if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } bf := byteframe.NewByteFrame() @@ -156,7 +166,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { ps.Uint8(bf, g.Name, true) ps.Uint8(bf, g.URLBanner, false) ps.Uint8(bf, g.URLFeature, false) - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { bf.WriteBool(g.Wide) ps.Uint8(bf, g.URLThumbnail, false) } @@ -166,23 +176,23 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(0) } bf.WriteUint8(g.GachaType) - if _config.ErupeConfig.ClientID >= _config.G10 { + if config.GetConfig().ClientID >= config.G10 { bf.WriteBool(g.Hidden) } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) case 2: // Actual gacha bf := byteframe.NewByteFrame() bf.WriteUint32(pkt.ShopID) var gachaType int - s.server.db.QueryRow(`SELECT gacha_type FROM gacha_shop WHERE id = $1`, pkt.ShopID).Scan(&gachaType) - rows, err := s.server.db.Queryx(`SELECT entry_type, id, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points, COALESCE(name, '') AS name FROM gacha_entries WHERE gacha_id = $1 ORDER BY weight DESC`, pkt.ShopID) + database.QueryRow(`SELECT gacha_type FROM gacha_shop WHERE id = $1`, pkt.ShopID).Scan(&gachaType) + rows, err := database.Queryx(`SELECT entry_type, id, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points, COALESCE(name, '') AS name FROM gacha_entries WHERE gacha_id = $1 ORDER BY weight DESC`, pkt.ShopID) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) return } var divisor float64 - s.server.db.QueryRow(`SELECT COALESCE(SUM(weight) / 100000.0, 0) AS chance FROM gacha_entries WHERE gacha_id = $1`, pkt.ShopID).Scan(&divisor) + database.QueryRow(`SELECT COALESCE(SUM(weight) / 100000.0, 0) AS chance FROM gacha_entries WHERE gacha_id = $1`, pkt.ShopID).Scan(&divisor) var entry GachaEntry var entries []GachaEntry @@ -209,7 +219,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(ge.Rarity) bf.WriteUint8(ge.Rolls) - rows, err = s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id=$1`, ge.ID) + rows, err = database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id=$1`, ge.ID) if err != nil { bf.WriteUint8(0) } else { @@ -235,7 +245,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(gi.Quantity) } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) case 3: // Hunting Festival Exchange fallthrough case 4: // N Points, 0-6 @@ -257,7 +267,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { items = items[:pkt.Limit] } writeShopItems(bf, items) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } } @@ -265,57 +275,73 @@ func handleMsgMhfAcquireExchangeShop(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfAcquireExchangeShop) bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) exchanges := int(bf.ReadUint16()) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } for i := 0; i < exchanges; i++ { itemHash := bf.ReadUint32() if itemHash == 0 { continue } buyCount := bf.ReadUint32() - s.server.db.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought) + database.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought) VALUES ($1,$2,$3) ON CONFLICT (character_id, shop_item_id) DO UPDATE SET bought = bought + $3 WHERE EXCLUDED.character_id=$1 AND EXCLUDED.shop_item_id=$2 - `, s.charID, itemHash, buyCount) + `, s.CharID, itemHash, buyCount) } - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfGetGachaPlayHistory(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGachaPlayHistory) bf := byteframe.NewByteFrame() bf.WriteUint8(1) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetGachaPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetGachaPoint) var fp, gp, gt uint32 - s.server.db.QueryRow("SELECT COALESCE(frontier_points, 0), COALESCE(gacha_premium, 0), COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.charID).Scan(&fp, &gp, >) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow("SELECT COALESCE(frontier_points, 0), COALESCE(gacha_premium, 0), COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.CharID).Scan(&fp, &gp, >) resp := byteframe.NewByteFrame() resp.WriteUint32(gp) resp.WriteUint32(gt) resp.WriteUint32(fp) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfUseGachaPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfUseGachaPoint) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if pkt.TrialCoins > 0 { - s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.TrialCoins, s.charID) + database.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.TrialCoins, s.CharID) } if pkt.PremiumCoins > 0 { - s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.PremiumCoins, s.charID) + database.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.PremiumCoins, s.CharID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func spendGachaCoin(s *Session, quantity uint16) { var gt uint16 - s.server.db.QueryRow(`SELECT COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(>) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow(`SELECT COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(>) if quantity <= gt { - s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID) + database.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.CharID) } else { - s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID) + database.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.CharID) } } @@ -323,7 +349,11 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (error, int) { var itemType uint8 var itemNumber uint16 var rolls int - err := s.server.db.QueryRowx(`SELECT item_type, item_number, rolls FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, gachaID, rollID).Scan(&itemType, &itemNumber, &rolls) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRowx(`SELECT item_type, item_number, rolls FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, gachaID, rollID).Scan(&itemType, &itemNumber, &rolls) if err != nil { return err, 0 } @@ -344,7 +374,7 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (error, int) { case 20: spendGachaCoin(s, itemNumber) case 21: - s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", itemNumber, s.charID) + database.Exec("UPDATE users u SET frontier_points=frontier_points-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", itemNumber, s.CharID) } return nil, rolls } @@ -352,7 +382,11 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (error, int) { func getGuaranteedItems(s *Session, gachaID uint32, rollID uint8) []GachaItem { var rewards []GachaItem var reward GachaItem - items, err := s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = (SELECT id FROM gacha_entries WHERE entry_type = $1 AND gacha_id = $2)`, rollID, gachaID) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + items, err := database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = (SELECT id FROM gacha_entries WHERE entry_type = $1 AND gacha_id = $2)`, rollID, gachaID) if err == nil { for items.Next() { items.StructScan(&reward) @@ -364,7 +398,11 @@ func getGuaranteedItems(s *Session, gachaID uint32, rollID uint8) []GachaItem { func addGachaItem(s *Session, items []GachaItem) { var data []byte - s.server.db.QueryRow(`SELECT gacha_items FROM characters WHERE id = $1`, s.charID).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow(`SELECT gacha_items FROM characters WHERE id = $1`, s.CharID).Scan(&data) if len(data) > 0 { numItems := int(data[0]) data = data[1:] @@ -384,7 +422,7 @@ func addGachaItem(s *Session, items []GachaItem) { newItem.WriteUint16(items[i].ItemID) newItem.WriteUint16(items[i].Quantity) } - s.server.db.Exec(`UPDATE characters SET gacha_items = $1 WHERE id = $2`, newItem.Data(), s.charID) + database.Exec(`UPDATE characters SET gacha_items = $1 WHERE id = $2`, newItem.Data(), s.CharID) } func getRandomEntries(entries []GachaEntry, rolls int, isBox bool) ([]GachaEntry, error) { @@ -419,7 +457,11 @@ func getRandomEntries(entries []GachaEntry, rolls int, isBox bool) ([]GachaEntry func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfReceiveGachaItem) var data []byte - err := s.server.db.QueryRow("SELECT COALESCE(gacha_items, $2) FROM characters WHERE id = $1", s.charID, []byte{0x00}).Scan(&data) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT COALESCE(gacha_items, $2) FROM characters WHERE id = $1", s.CharID, []byte{0x00}).Scan(&data) if err != nil { data = []byte{0x00} } @@ -429,9 +471,9 @@ func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) { resp := byteframe.NewByteFrame() resp.WriteUint8(36) resp.WriteBytes(data[1:181]) - doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + DoAckBufSucceed(s, pkt.AckHandle, resp.Data()) } else { - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } if !pkt.Freeze { @@ -439,9 +481,9 @@ func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) { update := byteframe.NewByteFrame() update.WriteUint8(uint8(len(data[181:]) / 5)) update.WriteBytes(data[181:]) - s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", update.Data(), s.charID) + database.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", update.Data(), s.CharID) } else { - s.server.db.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.charID) + database.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.CharID) } } } @@ -453,15 +495,19 @@ func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) { var entry GachaEntry var rewards []GachaItem var reward GachaItem + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } err, rolls := transactGacha(s, pkt.GachaID, pkt.RollType) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } - rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) + rows, err := database.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } for rows.Next() { @@ -475,7 +521,7 @@ func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) { rewardEntries, err := getRandomEntries(entries, rolls, false) temp := byteframe.NewByteFrame() for i := range rewardEntries { - rows, err = s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID) + rows, err = database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID) if err != nil { continue } @@ -494,7 +540,7 @@ func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(uint8(len(rewards))) bf.WriteBytes(temp.Data()) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) addGachaItem(s, rewards) } @@ -507,16 +553,20 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) { var reward GachaItem err, rolls := transactGacha(s, pkt.GachaID, pkt.RollType) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } - s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+(SELECT frontier_points FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.GachaID, pkt.RollType, s.charID) - s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID) - s.server.db.Exec(`INSERT INTO gacha_stepup (gacha_id, step, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, pkt.RollType+1, s.charID) - - rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) + database, err := db.GetDB() if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("UPDATE users u SET frontier_points=frontier_points+(SELECT frontier_points FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.GachaID, pkt.RollType, s.CharID) + database.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID) + database.Exec(`INSERT INTO gacha_stepup (gacha_id, step, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, pkt.RollType+1, s.CharID) + + rows, err := database.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) + if err != nil { + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } for rows.Next() { @@ -531,7 +581,7 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) { rewardEntries, err := getRandomEntries(entries, rolls, false) temp := byteframe.NewByteFrame() for i := range rewardEntries { - rows, err = s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID) + rows, err = database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID) if err != nil { continue } @@ -557,7 +607,7 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint8(0) } bf.WriteBytes(temp.Data()) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) addGachaItem(s, rewards) addGachaItem(s, guaranteedItems) } @@ -566,24 +616,32 @@ func handleMsgMhfGetStepupStatus(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetStepupStatus) // TODO: Reset daily (noon) var step uint8 - s.server.db.QueryRow(`SELECT step FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID).Scan(&step) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow(`SELECT step FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID).Scan(&step) var stepCheck int - s.server.db.QueryRow(`SELECT COUNT(1) FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, pkt.GachaID, step).Scan(&stepCheck) + database.QueryRow(`SELECT COUNT(1) FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, pkt.GachaID, step).Scan(&stepCheck) if stepCheck == 0 { - s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID) + database.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID) step = 0 } bf := byteframe.NewByteFrame() bf.WriteUint8(step) bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetBoxGachaInfo) - entries, err := s.server.db.Queryx(`SELECT entry_id FROM gacha_box WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID) + database, err := db.GetDB() if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + entries, err := database.Queryx(`SELECT entry_id FROM gacha_box WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID) + if err != nil { + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } var entryIDs []uint32 @@ -598,7 +656,7 @@ func handleMsgMhfGetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint32(entryIDs[i]) bf.WriteBool(true) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) { @@ -610,12 +668,16 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) { var reward GachaItem err, rolls := transactGacha(s, pkt.GachaID, pkt.RollType) if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } - rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) + database, err := db.GetDB() if err != nil { - doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) + if err != nil { + DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) return } for rows.Next() { @@ -626,11 +688,11 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) { } rewardEntries, err := getRandomEntries(entries, rolls, true) for i := range rewardEntries { - items, err := s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID) + items, err := database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID) if err != nil { continue } - s.server.db.Exec(`INSERT INTO gacha_box (gacha_id, entry_id, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, rewardEntries[i].ID, s.charID) + database.Exec(`INSERT INTO gacha_box (gacha_id, entry_id, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, rewardEntries[i].ID, s.CharID) for items.Next() { err = items.StructScan(&reward) if err == nil { @@ -645,38 +707,50 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(r.Quantity) bf.WriteUint8(0) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) addGachaItem(s, rewards) } func handleMsgMhfResetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfResetBoxGachaInfo) - s.server.db.Exec("DELETE FROM gacha_box WHERE gacha_id = $1 AND character_id = $2", pkt.GachaID, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.Exec("DELETE FROM gacha_box WHERE gacha_id = $1 AND character_id = $2", pkt.GachaID, s.CharID) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgMhfExchangeFpoint2Item(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfExchangeFpoint2Item) var balance uint32 var itemValue, quantity int - s.server.db.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue) cost := (int(pkt.Quantity) * quantity) * itemValue - s.server.db.QueryRow("UPDATE users u SET frontier_points=frontier_points::int - $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.charID).Scan(&balance) + database.QueryRow("UPDATE users u SET frontier_points=frontier_points::int - $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.CharID).Scan(&balance) bf := byteframe.NewByteFrame() bf.WriteUint32(balance) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfExchangeItem2Fpoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfExchangeItem2Fpoint) var balance uint32 var itemValue, quantity int - s.server.db.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue) cost := (int(pkt.Quantity) / quantity) * itemValue - s.server.db.QueryRow("UPDATE users u SET frontier_points=COALESCE(frontier_points::int + $1, $1) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.charID).Scan(&balance) + database.QueryRow("UPDATE users u SET frontier_points=COALESCE(frontier_points::int + $1, $1) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.CharID).Scan(&balance) bf := byteframe.NewByteFrame() bf.WriteUint32(balance) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } type FPointExchange struct { @@ -695,7 +769,11 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) { var exchange FPointExchange var exchanges []FPointExchange var buyables uint16 - rows, err := s.server.db.Queryx(`SELECT id, item_type, item_id, quantity, fpoints, buyable FROM fpoint_items ORDER BY buyable DESC`) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, err := database.Queryx(`SELECT id, item_type, item_id, quantity, fpoints, buyable FROM fpoint_items ORDER BY buyable DESC`) if err == nil { for rows.Next() { err = rows.StructScan(&exchange) @@ -708,7 +786,7 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) { exchanges = append(exchanges, exchange) } } - if _config.ErupeConfig.ClientID <= _config.Z2 { + if config.GetConfig().ClientID <= config.Z2 { bf.WriteUint8(uint8(len(exchanges))) bf.WriteUint8(uint8(buyables)) } else { @@ -726,12 +804,12 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(e.FPoints) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfPlayFreeGacha(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPlayFreeGacha) bf := byteframe.NewByteFrame() bf.WriteUint32(1) - doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_stage.go b/server/channelserver/handlers_stage.go index 107ab2b85..304916cf5 100644 --- a/server/channelserver/handlers_stage.go +++ b/server/channelserver/handlers_stage.go @@ -14,38 +14,38 @@ import ( func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateStage) - s.server.Lock() - defer s.server.Unlock() - if _, exists := s.server.stages[pkt.StageID]; exists { - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Server.Lock() + defer s.Server.Unlock() + if _, exists := s.Server.stages[pkt.StageID]; exists { + DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } else { stage := NewStage(pkt.StageID) stage.host = s stage.maxPlayers = uint16(pkt.PlayerCount) - s.server.stages[stage.id] = stage - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + s.Server.stages[stage.id] = stage + DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) } } func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {} func doStageTransfer(s *Session, ackHandle uint32, stageID string) { - s.server.Lock() - stage, exists := s.server.stages[stageID] - s.server.Unlock() + s.Server.Lock() + stage, exists := s.Server.stages[stageID] + s.Server.Unlock() if exists { stage.Lock() - stage.clients[s] = s.charID + stage.clients[s] = s.CharID stage.Unlock() } else { // Create new stage object - s.server.Lock() - s.server.stages[stageID] = NewStage(stageID) - stage = s.server.stages[stageID] - s.server.Unlock() + s.Server.Lock() + s.Server.stages[stageID] = NewStage(stageID) + stage = s.Server.stages[stageID] + s.Server.Unlock() stage.Lock() stage.host = s - stage.clients[s] = s.charID + stage.clients[s] = s.CharID stage.Unlock() } @@ -56,14 +56,14 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { // Save our new stage ID and pointer to the new stage itself. s.Lock() - s.stage = s.server.stages[stageID] + s.stage = s.Server.stages[stageID] s.Unlock() // Tell the client to cleanup its current stage objects. s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{}) // Confirm the stage entry. - doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00}) + DoAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00}) var temp mhfpacket.MHFPacket @@ -71,15 +71,15 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { if !s.userEnteredStage { s.userEnteredStage = true - for _, session := range s.server.sessions { + for _, session := range s.Server.sessions { if s == session { continue } - temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} + temp = &mhfpacket.MsgSysInsertUser{CharID: session.CharID} s.QueueSendMHF(temp) for i := 0; i < 3; i++ { temp = &mhfpacket.MsgSysNotifyUserBinary{ - CharID: session.charID, + CharID: session.CharID, BinaryType: uint8(i + 1), } s.QueueSendMHF(temp) @@ -89,10 +89,10 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { if s.stage != nil { // avoids lock up when using bed for dream quests // Notify the client to duplicate the existing objects. - s.logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name)) + s.Logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name)) s.stage.RLock() for _, obj := range s.stage.objects { - if obj.ownerCharID == s.charID { + if obj.ownerCharID == s.CharID { continue } temp = &mhfpacket.MsgSysDuplicateObject{ @@ -110,14 +110,14 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { } func destructEmptyStages(s *Session) { - s.server.Lock() - defer s.server.Unlock() - for _, stage := range s.server.stages { + s.Server.Lock() + defer s.Server.Unlock() + for _, stage := range s.Server.stages { // Destroy empty Quest/My series/Guild stages. if stage.id[3:5] == "Qs" || stage.id[3:5] == "Ms" || stage.id[3:5] == "Gs" || stage.id[3:5] == "Ls" { if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 { - delete(s.server.stages, stage.id) - s.logger.Debug("Destructed stage", zap.String("stage.id", stage.id)) + delete(s.Server.stages, stage.id) + s.Logger.Debug("Destructed stage", zap.String("stage.id", stage.id)) } } } @@ -128,9 +128,9 @@ func removeSessionFromStage(s *Session) { delete(s.stage.clients, s) // Delete old stage objects owned by the client. - s.logger.Info("Sending notification to old stage clients") + s.Logger.Info("Sending notification to old stage clients") for _, object := range s.stage.objects { - if object.ownerCharID == s.charID { + if object.ownerCharID == s.CharID { s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.id}, s) delete(s.stage.objects, object.ownerCharID) } @@ -140,8 +140,8 @@ func removeSessionFromStage(s *Session) { } func isStageFull(s *Session, StageID string) bool { - if stage, exists := s.server.stages[StageID]; exists { - if _, exists := stage.reservedClientSlots[s.charID]; exists { + if stage, exists := s.Server.stages[StageID]; exists { + if _, exists := stage.reservedClientSlots[s.CharID]; exists { return false } return len(stage.reservedClientSlots)+len(stage.clients) >= int(stage.maxPlayers) @@ -153,14 +153,14 @@ func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysEnterStage) if isStageFull(s, pkt.StageID) { - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) + DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) return } // Push our current stage ID to the movement stack before entering another one. if s.stage != nil { s.stage.Lock() - s.stage.reservedClientSlots[s.charID] = false + s.stage.reservedClientSlots[s.CharID] = false s.stage.Unlock() s.stageMoveStack.Push(s.stage.id) } @@ -183,16 +183,16 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) { if isStageFull(s, backStage) { s.stageMoveStack.Push(backStage) - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) + DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) return } - if _, exists := s.stage.reservedClientSlots[s.charID]; exists { - delete(s.stage.reservedClientSlots, s.charID) + if _, exists := s.stage.reservedClientSlots[s.CharID]; exists { + delete(s.stage.reservedClientSlots, s.CharID) } - if _, exists := s.server.stages[backStage].reservedClientSlots[s.charID]; exists { - delete(s.server.stages[backStage].reservedClientSlots, s.charID) + if _, exists := s.Server.stages[backStage].reservedClientSlots[s.CharID]; exists { + delete(s.Server.stages[backStage].reservedClientSlots, s.CharID) } doStageTransfer(s, pkt.AckHandle, backStage) @@ -202,7 +202,7 @@ func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysMoveStage) if isStageFull(s, pkt.StageID) { - doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) + DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01}) return } @@ -213,12 +213,12 @@ func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLockStage) - if stage, exists := s.server.stages[pkt.StageID]; exists { + if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() stage.locked = true stage.Unlock() } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { @@ -227,13 +227,13 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { defer s.reservationStage.RUnlock() for charID := range s.reservationStage.reservedClientSlots { - session := s.server.FindSessionByCharID(charID) + session := s.Server.FindSessionByCharID(charID) if session != nil { session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) } } - delete(s.server.stages, s.reservationStage.id) + delete(s.Server.stages, s.reservationStage.id) } destructEmptyStages(s) @@ -241,40 +241,40 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysReserveStage) - if stage, exists := s.server.stages[pkt.StageID]; exists { + if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() defer stage.Unlock() - if _, exists := stage.reservedClientSlots[s.charID]; exists { + if _, exists := stage.reservedClientSlots[s.CharID]; exists { switch pkt.Ready { case 1: // 0x01 - stage.reservedClientSlots[s.charID] = false + stage.reservedClientSlots[s.CharID] = false case 17: // 0x11 - stage.reservedClientSlots[s.charID] = true + stage.reservedClientSlots[s.CharID] = true } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers { if stage.locked { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } if len(stage.password) > 0 { if stage.password != s.stagePass { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) return } } - stage.reservedClientSlots[s.charID] = false + stage.reservedClientSlots[s.CharID] = false // Save the reservation stage in the session for later use in MsgSysUnreserveStage. s.Lock() s.reservationStage = stage s.Unlock() - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } else { - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } } else { - s.logger.Error("Failed to get stage", zap.String("StageID", pkt.StageID)) - doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + s.Logger.Error("Failed to get stage", zap.String("StageID", pkt.StageID)) + DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) } } @@ -285,8 +285,8 @@ func handleMsgSysUnreserveStage(s *Session, p mhfpacket.MHFPacket) { s.Unlock() if stage != nil { stage.Lock() - if _, exists := stage.reservedClientSlots[s.charID]; exists { - delete(stage.reservedClientSlots, s.charID) + if _, exists := stage.reservedClientSlots[s.CharID]; exists { + delete(stage.reservedClientSlots, s.CharID) } stage.Unlock() } @@ -300,7 +300,7 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) { if stage != nil { stage.Lock() // Will only exist if host. - if _, exists := stage.reservedClientSlots[s.charID]; exists { + if _, exists := stage.reservedClientSlots[s.CharID]; exists { stage.password = pkt.Password } stage.Unlock() @@ -314,78 +314,78 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysSetStageBinary) - if stage, exists := s.server.stages[pkt.StageID]; exists { + if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload stage.Unlock() } else { - s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) + s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) } } func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysGetStageBinary) - if stage, exists := s.server.stages[pkt.StageID]; exists { + if stage, exists := s.Server.stages[pkt.StageID]; exists { stage.Lock() if binaryData, exists := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]; exists { - doAckBufSucceed(s, pkt.AckHandle, binaryData) + DoAckBufSucceed(s, pkt.AckHandle, binaryData) } else if pkt.BinaryType1 == 4 { // Unknown binary type that is supposedly generated server side // Temporary response - doAckBufSucceed(s, pkt.AckHandle, []byte{}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{}) } else { - s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) - s.logger.Warn("Sending blank stage binary") - doAckBufSucceed(s, pkt.AckHandle, []byte{}) + s.Logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) + s.Logger.Warn("Sending blank stage binary") + DoAckBufSucceed(s, pkt.AckHandle, []byte{}) } stage.Unlock() } else { - s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) + s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) } - s.logger.Debug("MsgSysGetStageBinary Done!") + s.Logger.Debug("MsgSysGetStageBinary Done!") } func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysWaitStageBinary) - if stage, exists := s.server.stages[pkt.StageID]; exists { + if stage, exists := s.Server.stages[pkt.StageID]; exists { if pkt.BinaryType0 == 1 && pkt.BinaryType1 == 12 { // This might contain the hunter count, or max player count? - doAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) return } for { - s.logger.Debug("MsgSysWaitStageBinary before lock and get stage") + s.Logger.Debug("MsgSysWaitStageBinary before lock and get stage") stage.Lock() stageBinary, gotBinary := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] stage.Unlock() - s.logger.Debug("MsgSysWaitStageBinary after lock and get stage") + s.Logger.Debug("MsgSysWaitStageBinary after lock and get stage") if gotBinary { - doAckBufSucceed(s, pkt.AckHandle, stageBinary) + DoAckBufSucceed(s, pkt.AckHandle, stageBinary) break } else { - s.logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) + s.Logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) time.Sleep(1 * time.Second) continue } } } else { - s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) + s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID)) } - s.logger.Debug("MsgSysWaitStageBinary Done!") + s.Logger.Debug("MsgSysWaitStageBinary Done!") } func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysEnumerateStage) // Read-lock the server stage map. - s.server.stagesLock.RLock() - defer s.server.stagesLock.RUnlock() + s.Server.stagesLock.RLock() + defer s.Server.stagesLock.RUnlock() // Build the response bf := byteframe.NewByteFrame() var joinable uint16 bf.WriteUint16(0) - for sid, stage := range s.server.stages { + for sid, stage := range s.Server.stages { stage.RLock() if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 { @@ -420,5 +420,5 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { bf.Seek(0, 0) bf.WriteUint16(joinable) - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_tactics.go b/server/channelserver/handlers_tactics.go index 62c001156..ee94ec34d 100644 --- a/server/channelserver/handlers_tactics.go +++ b/server/channelserver/handlers_tactics.go @@ -11,7 +11,7 @@ func handleMsgMhfGetUdTacticsPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsPoint) // Temporary canned response data, _ := hex.DecodeString("000000A08F0BE2DAE30BE30AE2EAE2E9E2E8E2F5E2F3E2F2E2F1E2BB") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfAddUdTacticsPoint(s *Session, p mhfpacket.MHFPacket) { @@ -24,40 +24,40 @@ func handleMsgMhfGetUdTacticsRewardList(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsRewardList) // Temporary canned response data, _ := hex.DecodeString("000094000000010732DD00010000000000010732DD00010100000000C8071F2800050100000000C80705C000050000000001901A000001F40000000001901A000001F40100000002580705C00005000000000258071F2800050100000003201A000003E80100000003201A000003E80000000003E81A000004B00100000003E81A000004B00000000004B01A000005DC0100000004B01A000005DC0000000005781A000008FC0100000005781A000008FC0000000006401A000009C40000000006401A000009C40100000007081A00000BB80100000007081A00000BB80000000007D00725FA00010000000007D01A00000CE40000000007D00725FC00010100000007D00725FB00010100000007D00725FA00010100000007D01A00000CE40100000007D00725FC00010000000007D00725FB0001000000000BB80705C00005000000000BB8071F280005010000000FA01A00000DAC000000000FA01A00000DAC0100000013880705C00005000000001388071F2800050100000017700725FE00010100000017700725FD00010100000017700725FF00010100000017700725FD00010000000017700725FE00010000000017700725FF0001000000001B581A00000E74000000001B581A00000E74010000001F400727D00005010000001F400727D000050000000023281A00000FA00000000023281A00000FA00100000027100736EF000100000000271007369600010100000027100736EF00010100000027100736EF0001000000002EE00727D10005010000002EE00727D100050000000036B01D000000010100000036B01D00000001000000003A980737DB0001010000003A980736EF00010000000046500725E600010100000046500725E60001000000004E200738C90001010000004E200736EF00010000000055F01A000010680100000055F01A000010680000000061A80736EF00010000000061A80739A600010100000065900727D200050000000065900727D20005010000007530073A0600010100000075300736EF00010000000075300736EF00010000000075300736EF00010100000084D01D000000020000000084D01D00000002010000009C400727D30005010000009C400727D3000500000000B3B01A0000119400000000B3B01A0000119401000000C3500727D4000500000000C3500727D4000501000000D2F01D0000000300000000D2F01D0000000301000000EA600736EF000100000000EA600736EF000101000000F6181A0000125C00000000F6181A0000125C0100000111700727D500050000000111700727D500050100000119400727D600050100000119400727D600050000000121101D000000040000000121101D000000040100000130B01A000013880000000130B01A000013880100000140500727D700050000000140500727D700050100000148201D000000050000000148201D00000005010000014FF01A000014B4000000014FF01A000014B4010000015F900736EF0001000000015F900736EF00010100000167600729EA00050000000167600729EA0005010000016F301D00000006010000016F301D00000006000000017ED00729EB0005000000017ED00729EB0005010000018E701A0000157C010000018E701A0000157C0000000196401D000000070000000196401D00000007010000019E100729EC0005000000019E100729EC000501000001ADB00727CD000100000001ADB00727CD000101000001BD501D0000000800000001BD501D0000000801000001CCF01A0000164401000001CCF01A0000164400000001E4601D0000000901000001E4601D0000000900000001EC300727CC000101000001EC300727CC0001000000020B701D0000000A000000020B701D0000000A010000023A501A0000170C010000023A501A0000170C0000000249F00736EF00010100000249F00736EF00010000000271001A000017D40100000271001A000017D400000002A7B01A0000189C01000002A7B01A0000189C00000002BF200736EF000100000002BF200736EF000101000002D6901A0000196401000002D6901A00001964000000030D400727CB0001000000030D400727CB00010100000343F01A00001A2C0100000343F01A00001A2C0000000372D0072CB0000F0000000372D0072CB0000F01000003A9801A00001BBC00000003A9801A00001BBC01000003F7A01A000003E800010003F7A01A000003E80101000445C01A000003E80101000445C01A000003E80001005E000000020704020005010000000002070402000500000000000307040200140000000000030704020014010000000005071D200003010000000005071D20000300000000000607040200140100000000060704020014000000000008071D210003010000000008071D21000300000000000A070402001401000000000A070402001400000000000C0722EC000501000000000C0722ED000500000000000C0722F2000500000000000C0722EC000500000000000C0722EF000500000000000C0722ED000501000000000C0722F2000501000000000C0722EF000501000000000D1A000003E801000000000D1A000003E800000000000F07357C000501000000000F07357D000501000000000F07357C000500000000000F07357D00050000000000111A000007D00000000000111A000007D00100000000141C00000001000000000014071D2200030000000000141C00000001010000000014071D22000301000000001607357D000701000000001607357C00070000000000160704020028000000000016070402002801000000001607357C000701000000001607357D0007000000000018071D270003000000000018071D27000301000000001A1A00000BB800000000001A1A00000BB801000000001C07357D000701000000001C070402002801000000001C07357D000700000000001C07357C000700000000001C070402002800000000001C07357C000701000000001E070402003C01000000001E070402003C000000000020071D26000301000000002007357C000700000000002007357D000700000000002007357C000701000000002007357D0007010000000020071D260003000000000023071D280003010000000023071D28000300000000002A070402003C00000000002A070402003C01000000002C0725EE000100000000002C0725EE000101000000002E070402005001000000002E07357D000A01000000002E070402005000000000002E07357C000A00000000002E07357D000A00000000002E07357C000A0100000000300725ED00010000000000300725ED0001010000000032071D200003010000000032071D200003000000000034072C7B0001000000000034072C7B0001010000000037071D210003000000000037071D21000301000000003C0722F1000A00000000003C0722F1000A01000000004107040200500000000000410704020050010000000046071D220003010000000046071D22000300000000004B071D27000301000000004B071D2700030000000000500722F1000F0100000000500722F1000F0000000000550704020050010000000055070402005000000000005A071D26000301000000005A071D26000300000000005F071D28000300000000005F071D2800030100000000641A0000C3500100000000641A0000C3500000002607000E00C8000000010000000307000F0032000000010000000307001000320000000100000003070011003200000001000000030700120032000000010000000307000E0096000000040000000A07000F0028000000040000000A0700100028000000040000000A0700110028000000040000000A0700120028000000040000000A07000E00640000000B0000001907000F001E0000000B00000019070010001E0000000B00000019070011001E0000000B00000019070012001E0000000B0000001907000E00320000001A0000002807000F00140000001A0000002807001000140000001A0000002807001100140000001A0000002807001200140000001A0000002807000E001E000000290000004607000F000A0000002900000046070010000A000000290000004607001100010000002900000046070012000A000000290000004607000E0019000000470000006407000F0008000000470000006407001000080000004700000064070011000100000047000000640700120008000000470000006407000E000F000000650000009607000F0006000000650000009607001000010000006500000096070011000600000065000000960700120006000000650000009607000E000500000097000001F407000F000500000097000001F4070010000500000097000001F4") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetUdTacticsFollower(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsFollower) - doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) } func handleMsgMhfGetUdTacticsBonusQuest(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsBonusQuest) // Temporary canned response data, _ := hex.DecodeString("14E2F55DCBFE505DCC1A7003E8E2C55DCC6ED05DCC8AF00258E2CE5DCCDF505DCCFB700279E3075DCD4FD05DCD6BF0041AE2F15DCDC0505DCDDC700258E2C45DCE30D05DCE4CF00258E2F55DCEA1505DCEBD7003E8E2C25DCF11D05DCF2DF00258E2CE5DCF82505DCF9E700279E3075DCFF2D05DD00EF0041AE2CE5DD063505DD07F700279E2F35DD0D3D05DD0EFF0028AE2C35DD144505DD160700258E2F05DD1B4D05DD1D0F00258E2CE5DD225505DD241700279E2F55DD295D05DD2B1F003E8E2F25DD306505DD3227002EEE2CA5DD376D05DD392F00258E3075DD3E7505DD40370041AE2F55DD457D05DD473F003E82027313220686F757273273A3A696E74657276616C29202B2027313220686F757273273A3A696E74657276616C2047524F5550204259206D6170204F52444552204259206D61703B2000C7312B000032") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetUdTacticsFirstQuestBonus(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsFirstQuestBonus) // Temporary canned response data, _ := hex.DecodeString("0500000005DC01000007D002000009C40300000BB80400001194") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfGetUdTacticsRemainingPoint(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsRemainingPoint) bf := byteframe.NewByteFrame() bf.WriteUint32(0) // Points until Special Guild Hall earned - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfGetUdTacticsRanking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetUdTacticsRanking) // Temporary canned response data, _ := hex.DecodeString("00000515000005150000CEB4000003CE000003CE0000CEB44D49444E494748542D414E47454C0000000000000000000000") - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } func handleMsgMhfSetUdTacticsFollower(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_tournament.go b/server/channelserver/handlers_tournament.go index c209e4f53..0ada97d56 100644 --- a/server/channelserver/handlers_tournament.go +++ b/server/channelserver/handlers_tournament.go @@ -103,12 +103,12 @@ func handleMsgMhfInfoTournament(s *Session, p mhfpacket.MHFPacket) { } } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } func handleMsgMhfEntryTournament(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfEntryTournament) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } type TournamentReward struct { @@ -127,5 +127,5 @@ func handleMsgMhfAcquireTournament(s *Session, p mhfpacket.MHFPacket) { bf.WriteUint16(reward.Unk1) bf.WriteUint16(reward.Unk2) } - doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + DoAckBufSucceed(s, pkt.AckHandle, bf.Data()) } diff --git a/server/channelserver/handlers_tower.go b/server/channelserver/handlers_tower.go index 42dcdaff8..b1c564168 100644 --- a/server/channelserver/handlers_tower.go +++ b/server/channelserver/handlers_tower.go @@ -1,7 +1,7 @@ package channelserver import ( - _config "erupe-ce/config" + "erupe-ce/config" "fmt" "strings" "time" @@ -10,6 +10,7 @@ import ( "erupe-ce/network/mhfpacket" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/stringsupport" ) @@ -59,15 +60,18 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}}, Level: []TowerInfoLevel{{0, 0, 0, 0}, {0, 0, 0, 0}}, } - - var tempSkills string - err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), COALESCE(skills, $1) FROM tower WHERE char_id=$2 - `, EmptyTowerCSV(64), s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Floors, &towerInfo.Level[1].Floors, &tempSkills) + database, err := db.GetDB() if err != nil { - s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var tempSkills string + err = database.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), COALESCE(skills, $1) FROM tower WHERE char_id=$2 + `, EmptyTowerCSV(64), 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 { + database.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.CharID) } - if _config.ErupeConfig.ClientID <= _config.G7 { + if config.GetConfig().ClientID <= config.G7 { towerInfo.Level = towerInfo.Level[:1] } @@ -113,14 +117,14 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTowerInfo) - if s.server.erupeConfig.DebugOptions.QuestTools { - s.logger.Debug( + if config.GetConfig().DebugOptions.QuestTools { + s.Logger.Debug( p.Opcode().String(), zap.Uint32("InfoType", pkt.InfoType), zap.Uint32("Unk1", pkt.Unk1), @@ -134,17 +138,20 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { zap.Int64("Unk9", pkt.Unk9), ) } - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch pkt.InfoType { case 2: var skills string - s.server.db.QueryRow(`SELECT COALESCE(skills, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(64), 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) + database.QueryRow(`SELECT COALESCE(skills, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(64), s.CharID).Scan(&skills) + database.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 1, 7: // This might give too much TSP? No idea what the rate is supposed to be - s.server.db.Exec(`UPDATE tower SET tr=$1, trp=COALESCE(trp, 0)+$2, tsp=COALESCE(tsp, 0)+$3, block1=COALESCE(block1, 0)+$4 WHERE char_id=$5`, pkt.TR, pkt.TRP, pkt.Cost, pkt.Block1, s.charID) + database.Exec(`UPDATE tower SET tr=$1, trp=COALESCE(trp, 0)+$2, tsp=COALESCE(tsp, 0)+$3, block1=COALESCE(block1, 0)+$4 WHERE char_id=$5`, pkt.TR, pkt.TRP, pkt.Cost, pkt.Block1, s.CharID) } - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } // Default missions @@ -250,7 +257,10 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { Data: tenrouiraiData, Ticket: []TenrouiraiTicket{{0, 0, 0}}, } - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch pkt.Unk1 { case 1: for _, tdata := range tenrouirai.Data { @@ -284,8 +294,8 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { 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 + database.QueryRow(`SELECT tower_mission_page FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Page) + database.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 { @@ -313,7 +323,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { 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) + rows, _ := database.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) @@ -326,7 +336,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { 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) + database.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) @@ -336,14 +346,17 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { } } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostTenrouirai) - - if s.server.erupeConfig.DebugOptions.QuestTools { - s.logger.Debug( + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + if config.GetConfig().DebugOptions.QuestTools { + s.Logger.Debug( p.Opcode().String(), zap.Uint8("Unk0", pkt.Unk0), zap.Uint8("Op", pkt.Op), @@ -360,7 +373,7 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { if pkt.Op == 2 { var page, requirement, donated int - s.server.db.QueryRow(`SELECT tower_mission_page, tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&page, &donated) + database.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) @@ -368,24 +381,24 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() - sd, err := GetCharacterSaveData(s, s.charID) + 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) + database.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID) + database.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) + database.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()) + DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } else { - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } } @@ -405,7 +418,7 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) { bf.WriteInt32(0) bf.WriteInt32(0) */ - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } type GemInfo struct { @@ -425,9 +438,12 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { var data []*byteframe.ByteFrame gemInfo := []GemInfo{} gemHistory := []GemHistory{} - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var tempGems string - s.server.db.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.charID).Scan(&tempGems) + database.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.CharID).Scan(&tempGems) for i, v := range stringsupport.CSVElems(tempGems) { gemInfo = append(gemInfo, GemInfo{uint16((i / 5 << 8) + (i%5 + 1)), uint16(v)}) } @@ -450,14 +466,14 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) { data = append(data, bf) } } - doAckEarthSucceed(s, pkt.AckHandle, data) + DoAckEarthSucceed(s, pkt.AckHandle, data) } func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfPostGemInfo) - if s.server.erupeConfig.DebugOptions.QuestTools { - s.logger.Debug( + if config.GetConfig().DebugOptions.QuestTools { + s.Logger.Debug( p.Opcode().String(), zap.Uint32("Op", pkt.Op), zap.Uint32("Unk1", pkt.Unk1), @@ -468,25 +484,28 @@ func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) { zap.Int32("Unk6", pkt.Unk6), ) } - + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } var gems string - s.server.db.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.charID).Scan(&gems) + database.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.CharID).Scan(&gems) switch pkt.Op { case 1: // Add gem i := int((pkt.Gem >> 8 * 5) + (pkt.Gem - pkt.Gem&0xFF00 - 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) + database.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 handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetNotice) - doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) + 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)) + DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } diff --git a/server/channelserver/handlers_users.go b/server/channelserver/handlers_users.go index fc8b47a8d..2df4847f2 100644 --- a/server/channelserver/handlers_users.go +++ b/server/channelserver/handlers_users.go @@ -4,6 +4,7 @@ import ( "fmt" "erupe-ce/network/mhfpacket" + "erupe-ce/utils/db" ) func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {} @@ -12,44 +13,50 @@ func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysSetUserBinary) - s.server.userBinaryPartsLock.Lock() - s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload - s.server.userBinaryPartsLock.Unlock() - - var exists []byte - err := s.server.db.QueryRow("SELECT type2 FROM user_binary WHERE id=$1", s.charID).Scan(&exists) + s.Server.userBinaryPartsLock.Lock() + s.Server.userBinaryParts[userBinaryPartID{charID: s.CharID, index: pkt.BinaryType}] = pkt.RawDataPayload + s.Server.userBinaryPartsLock.Unlock() + database, err := db.GetDB() if err != nil { - s.server.db.Exec("INSERT INTO user_binary (id) VALUES ($1)", s.charID) + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var exists []byte + err = database.QueryRow("SELECT type2 FROM user_binary WHERE id=$1", s.CharID).Scan(&exists) + if err != nil { + database.Exec("INSERT INTO user_binary (id) VALUES ($1)", s.CharID) } - s.server.db.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID) + database.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.CharID) msg := &mhfpacket.MsgSysNotifyUserBinary{ - CharID: s.charID, + CharID: s.CharID, BinaryType: pkt.BinaryType, } - s.server.BroadcastMHF(msg, s) + s.Server.BroadcastMHF(msg, s) } func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysGetUserBinary) // Try to get the data. - s.server.userBinaryPartsLock.RLock() - defer s.server.userBinaryPartsLock.RUnlock() - data, ok := s.server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}] - + s.Server.userBinaryPartsLock.RLock() + defer s.Server.userBinaryPartsLock.RUnlock() + data, ok := s.Server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}] + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } // If we can't get the real data, try to get it from the database. if !ok { - err := s.server.db.QueryRow(fmt.Sprintf("SELECT type%d FROM user_binary WHERE id=$1", pkt.BinaryType), pkt.CharID).Scan(&data) + err = database.QueryRow(fmt.Sprintf("SELECT type%d FROM user_binary WHERE id=$1", pkt.BinaryType), pkt.CharID).Scan(&data) if err != nil { - doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + DoAckBufFail(s, pkt.AckHandle, make([]byte, 4)) } else { - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } } else { - doAckBufSucceed(s, pkt.AckHandle, data) + DoAckBufSucceed(s, pkt.AckHandle, data) } } diff --git a/server/channelserver/sys_broadcast.go b/server/channelserver/sys_broadcast.go index 52f9181ff..327cb17f1 100644 --- a/server/channelserver/sys_broadcast.go +++ b/server/channelserver/sys_broadcast.go @@ -10,7 +10,7 @@ import ( ) // BroadcastMHF queues a MHFPacket to be sent to all sessions. -func (server *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { +func (server *ChannelServer) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { // Broadcast the data. server.Lock() defer server.Unlock() @@ -22,7 +22,7 @@ func (server *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Sess } } -func (server *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session, ignoredChannel *Server) { +func (server *ChannelServer) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session, ignoredChannel *ChannelServer) { for _, c := range server.Channels { if c == ignoredChannel { continue @@ -32,7 +32,7 @@ func (server *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Sess } // BroadcastChatMessage broadcasts a simple chat message to all the sessions. -func (server *Server) BroadcastChatMessage(message string) { +func (server *ChannelServer) BroadcastChatMessage(message string) { bf := byteframe.NewByteFrame() bf.SetLE() msgBinChat := &binpacket.MsgBinChat{ @@ -50,7 +50,7 @@ func (server *Server) BroadcastChatMessage(message string) { }, nil) } -func (server *Server) BroadcastRaviente(ip uint32, port uint16, stage []byte, _type uint8) { +func (server *ChannelServer) BroadcastRaviente(ip uint32, port uint16, stage []byte, _type uint8) { bf := byteframe.NewByteFrame() bf.SetLE() bf.WriteUint16(0) // Unk diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index fae6c3244..77d935515 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -6,23 +6,21 @@ import ( "sync" "time" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/server/discordbot" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" "erupe-ce/utils/logger" - "github.com/jmoiron/sqlx" "go.uber.org/zap" ) // Config struct allows configuring the server. type Config struct { - ID uint16 - DB *sqlx.DB - DiscordBot *discordbot.DiscordBot - ErupeConfig *_config.Config - Name string - Enable bool + ID uint16 + DiscordBot *discordbot.DiscordBot + Name string + Enable bool } // Map key type for a user binary part. @@ -31,17 +29,16 @@ type userBinaryPartID struct { index uint8 } -// Server is a MHF channel server. -type Server struct { +// ChannelServer is a MHF channel server. +type ChannelServer struct { sync.Mutex - Channels []*Server + Channels []*ChannelServer ID uint16 GlobalID string IP string Port uint16 logger logger.Logger - db *sqlx.DB - erupeConfig *_config.Config + erupeConfig *config.Config acceptConns chan net.Conn deleteConns chan net.Conn sessions map[net.Conn]*Session @@ -76,7 +73,7 @@ type Server struct { } // NewServer creates a new Server type. -func NewServer(config *Config) *Server { +func NewServer(config *Config) *ChannelServer { stageNames := []string{ "sl1Ns200p0a0u0", // Mezeporta "sl1Ns211p0a0u0", // Rasta bar @@ -90,11 +87,9 @@ func NewServer(config *Config) *Server { for _, name := range stageNames { stages[name] = NewStage(name) } - server := &Server{ + server := &ChannelServer{ ID: config.ID, logger: logger.Get().Named("channel-" + fmt.Sprint(config.ID)), - db: config.DB, - erupeConfig: config.ErupeConfig, acceptConns: make(chan net.Conn), deleteConns: make(chan net.Conn), sessions: make(map[net.Conn]*Session), @@ -121,7 +116,7 @@ func NewServer(config *Config) *Server { } // Start starts the server in a new goroutine. -func (server *Server) Start() error { +func (server *ChannelServer) Start() error { l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.Port)) if err != nil { return err @@ -130,9 +125,8 @@ func (server *Server) Start() error { go server.acceptClients() go server.manageSessions() - // Start the discord bot for chat integration. - if server.erupeConfig.Discord.Enabled && server.discordBot != nil { + if config.GetConfig().Discord.Enabled && server.discordBot != nil { server.discordBot.Session.AddHandler(server.onDiscordMessage) server.discordBot.Session.AddHandler(server.onInteraction) } @@ -141,7 +135,7 @@ func (server *Server) Start() error { } // Shutdown tries to shut down the server gracefully. -func (server *Server) Shutdown() { +func (server *ChannelServer) Shutdown() { server.Lock() server.isShuttingDown = true server.Unlock() @@ -151,7 +145,7 @@ func (server *Server) Shutdown() { close(server.acceptConns) } -func (server *Server) acceptClients() { +func (server *ChannelServer) acceptClients() { for { conn, err := server.listener.Accept() if err != nil { @@ -170,7 +164,7 @@ func (server *Server) acceptClients() { } } -func (server *Server) manageSessions() { +func (server *ChannelServer) manageSessions() { for { select { case newConn := <-server.acceptConns: @@ -201,10 +195,10 @@ func (server *Server) manageSessions() { } } -func (server *Server) FindSessionByCharID(charID uint32) *Session { +func (server *ChannelServer) FindSessionByCharID(charID uint32) *Session { for _, c := range server.Channels { for _, session := range c.sessions { - if session.charID == charID { + if session.CharID == charID { return session } } @@ -212,10 +206,14 @@ func (server *Server) FindSessionByCharID(charID uint32) *Session { return nil } -func (server *Server) DisconnectUser(uid uint32) { +func (server *ChannelServer) DisconnectUser(uid uint32) { var cid uint32 var cids []uint32 - rows, _ := server.db.Query(`SELECT id FROM characters WHERE user_id=$1`, uid) + database, err := db.GetDB() + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + rows, _ := database.Query(`SELECT id FROM characters WHERE user_id=$1`, uid) for rows.Next() { rows.Scan(&cid) cids = append(cids, cid) @@ -223,7 +221,7 @@ func (server *Server) DisconnectUser(uid uint32) { for _, c := range server.Channels { for _, session := range c.sessions { for _, cid := range cids { - if session.charID == cid { + if session.CharID == cid { session.rawConn.Close() break } @@ -232,7 +230,7 @@ func (server *Server) DisconnectUser(uid uint32) { } } -func (server *Server) FindObjectByChar(charID uint32) *Object { +func (server *ChannelServer) FindObjectByChar(charID uint32) *Object { server.stagesLock.RLock() defer server.stagesLock.RUnlock() for _, stage := range server.stages { @@ -250,7 +248,7 @@ func (server *Server) FindObjectByChar(charID uint32) *Object { return nil } -func (server *Server) HasSemaphore(ses *Session) bool { +func (server *ChannelServer) HasSemaphore(ses *Session) bool { for _, semaphore := range server.semaphore { if semaphore.host == ses { return true @@ -259,7 +257,7 @@ func (server *Server) HasSemaphore(ses *Session) bool { return false } -func (server *Server) Season() uint8 { +func (server *ChannelServer) Season() uint8 { sid := int64(((server.ID & 0xFF00) - 4096) / 256) return uint8(((gametime.TimeAdjusted().Unix() / 86400) + sid) % 3) } diff --git a/server/channelserver/sys_discord.go b/server/channelserver/sys_discord.go index c05f292be..939438e4a 100644 --- a/server/channelserver/sys_discord.go +++ b/server/channelserver/sys_discord.go @@ -1,6 +1,7 @@ package channelserver import ( + "erupe-ce/utils/db" "fmt" "sort" "strings" @@ -15,7 +16,7 @@ type Player struct { QuestID int } -func getPlayerSlice(server *Server) []Player { +func getPlayerSlice(server *ChannelServer) []Player { var p []Player var questIndex int @@ -40,7 +41,7 @@ func getPlayerSlice(server *Server) []Player { return p } -func getCharacterList(server *Server) string { +func getCharacterList(server *ChannelServer) string { questEmojis := []string{ ":person_in_lotus_position:", ":white_circle:", @@ -69,11 +70,15 @@ func getCharacterList(server *Server) string { } // onInteraction handles slash commands -func (server *Server) onInteraction(ds *discordgo.Session, i *discordgo.InteractionCreate) { +func (server *ChannelServer) onInteraction(ds *discordgo.Session, i *discordgo.InteractionCreate) { + database, err := db.GetDB() + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } switch i.Interaction.ApplicationCommandData().Name { case "link": var temp string - err := server.db.QueryRow(`UPDATE users SET discord_id = $1 WHERE discord_token = $2 RETURNING discord_id`, i.Member.User.ID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&temp) + err := database.QueryRow(`UPDATE users SET discord_id = $1 WHERE discord_token = $2 RETURNING discord_id`, i.Member.User.ID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&temp) if err == nil { ds.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, @@ -93,7 +98,7 @@ func (server *Server) onInteraction(ds *discordgo.Session, i *discordgo.Interact } case "password": password, _ := bcrypt.GenerateFromPassword([]byte(i.ApplicationCommandData().Options[0].StringValue()), 10) - _, err := server.db.Exec(`UPDATE users SET password = $1 WHERE discord_id = $2`, password, i.Member.User.ID) + _, err := database.Exec(`UPDATE users SET password = $1 WHERE discord_id = $2`, password, i.Member.User.ID) if err == nil { ds.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, @@ -115,7 +120,7 @@ func (server *Server) onInteraction(ds *discordgo.Session, i *discordgo.Interact } // onDiscordMessage handles receiving messages from discord and forwarding them ingame. -func (server *Server) onDiscordMessage(ds *discordgo.Session, m *discordgo.MessageCreate) { +func (server *ChannelServer) onDiscordMessage(ds *discordgo.Session, m *discordgo.MessageCreate) { // Ignore messages from bots, or messages that are not in the correct channel. if m.Author.Bot || m.ChannelID != server.erupeConfig.Discord.RelayChannel.RelayChannelID { return @@ -148,14 +153,14 @@ func (server *Server) onDiscordMessage(ds *discordgo.Session, m *discordgo.Messa server.BroadcastChatMessage(messages[i]) } } -func (server *Server) DiscordChannelSend(charName string, content string) { +func (server *ChannelServer) DiscordChannelSend(charName string, content string) { if server.erupeConfig.Discord.Enabled && server.discordBot != nil { message := fmt.Sprintf("**%s**: %s", charName, content) server.discordBot.RealtimeChannelSend(message) } } -func (server *Server) DiscordScreenShotSend(charName string, title string, description string, articleToken string) { +func (server *ChannelServer) DiscordScreenShotSend(charName string, title string, description string, articleToken string) { if server.erupeConfig.Discord.Enabled && server.discordBot != nil { imageUrl := fmt.Sprintf("%s:%d/api/ss/bbs/%s", server.erupeConfig.Screenshots.Host, server.erupeConfig.Screenshots.Port, articleToken) message := fmt.Sprintf("**%s**: %s - %s %s", charName, title, description, imageUrl) diff --git a/server/channelserver/handlers_table.go b/server/channelserver/sys_handlers_table.go similarity index 89% rename from server/channelserver/handlers_table.go rename to server/channelserver/sys_handlers_table.go index db46ad689..2c6d64769 100644 --- a/server/channelserver/handlers_table.go +++ b/server/channelserver/sys_handlers_table.go @@ -155,14 +155,14 @@ func init() { handlerTable[network.MSG_MHF_CARAVAN_MY_SCORE] = handleMsgMhfCaravanMyScore handlerTable[network.MSG_MHF_CARAVAN_RANKING] = handleMsgMhfCaravanRanking handlerTable[network.MSG_MHF_CARAVAN_MY_RANK] = handleMsgMhfCaravanMyRank - handlerTable[network.MSG_MHF_CREATE_GUILD] = handleMsgMhfCreateGuild - handlerTable[network.MSG_MHF_OPERATE_GUILD] = handleMsgMhfOperateGuild - handlerTable[network.MSG_MHF_OPERATE_GUILD_MEMBER] = handleMsgMhfOperateGuildMember - handlerTable[network.MSG_MHF_INFO_GUILD] = handleMsgMhfInfoGuild - handlerTable[network.MSG_MHF_ENUMERATE_GUILD] = handleMsgMhfEnumerateGuild - handlerTable[network.MSG_MHF_UPDATE_GUILD] = handleMsgMhfUpdateGuild - handlerTable[network.MSG_MHF_ARRANGE_GUILD_MEMBER] = handleMsgMhfArrangeGuildMember - handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MEMBER] = handleMsgMhfEnumerateGuildMember + handlerTable[network.MSG_MHF_CREATE_GUILD] = HandleMsgMhfCreateGuild + handlerTable[network.MSG_MHF_OPERATE_GUILD] = HandleMsgMhfOperateGuild + handlerTable[network.MSG_MHF_OPERATE_GUILD_MEMBER] = HandleMsgMhfOperateGuildMember + handlerTable[network.MSG_MHF_INFO_GUILD] = HandleMsgMhfInfoGuild + handlerTable[network.MSG_MHF_ENUMERATE_GUILD] = HandleMsgMhfEnumerateGuild + handlerTable[network.MSG_MHF_UPDATE_GUILD] = HandleMsgMhfUpdateGuild + handlerTable[network.MSG_MHF_ARRANGE_GUILD_MEMBER] = HandleMsgMhfArrangeGuildMember + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MEMBER] = HandleMsgMhfEnumerateGuildMember handlerTable[network.MSG_MHF_ENUMERATE_CAMPAIGN] = handleMsgMhfEnumerateCampaign handlerTable[network.MSG_MHF_STATE_CAMPAIGN] = handleMsgMhfStateCampaign handlerTable[network.MSG_MHF_APPLY_CAMPAIGN] = handleMsgMhfApplyCampaign @@ -170,7 +170,7 @@ func init() { handlerTable[network.MSG_MHF_ACQUIRE_ITEM] = handleMsgMhfAcquireItem handlerTable[network.MSG_MHF_TRANSFER_ITEM] = handleMsgMhfTransferItem handlerTable[network.MSG_MHF_MERCENARY_HUNTDATA] = handleMsgMhfMercenaryHuntdata - handlerTable[network.MSG_MHF_ENTRY_ROOKIE_GUILD] = handleMsgMhfEntryRookieGuild + handlerTable[network.MSG_MHF_ENTRY_ROOKIE_GUILD] = HandleMsgMhfEntryRookieGuild handlerTable[network.MSG_MHF_ENUMERATE_QUEST] = handleMsgMhfEnumerateQuest handlerTable[network.MSG_MHF_ENUMERATE_EVENT] = handleMsgMhfEnumerateEvent handlerTable[network.MSG_MHF_ENUMERATE_PRICE] = handleMsgMhfEnumeratePrice @@ -187,14 +187,14 @@ func init() { handlerTable[network.MSG_MHF_UPDATE_WAREHOUSE] = handleMsgMhfUpdateWarehouse handlerTable[network.MSG_MHF_ACQUIRE_TITLE] = handleMsgMhfAcquireTitle handlerTable[network.MSG_MHF_ENUMERATE_TITLE] = handleMsgMhfEnumerateTitle - handlerTable[network.MSG_MHF_ENUMERATE_GUILD_ITEM] = handleMsgMhfEnumerateGuildItem - handlerTable[network.MSG_MHF_UPDATE_GUILD_ITEM] = handleMsgMhfUpdateGuildItem + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_ITEM] = HandleMsgMhfEnumerateGuildItem + handlerTable[network.MSG_MHF_UPDATE_GUILD_ITEM] = HandleMsgMhfUpdateGuildItem handlerTable[network.MSG_MHF_ENUMERATE_UNION_ITEM] = handleMsgMhfEnumerateUnionItem handlerTable[network.MSG_MHF_UPDATE_UNION_ITEM] = handleMsgMhfUpdateUnionItem - handlerTable[network.MSG_MHF_CREATE_JOINT] = handleMsgMhfCreateJoint - handlerTable[network.MSG_MHF_OPERATE_JOINT] = handleMsgMhfOperateJoint - handlerTable[network.MSG_MHF_INFO_JOINT] = handleMsgMhfInfoJoint - handlerTable[network.MSG_MHF_UPDATE_GUILD_ICON] = handleMsgMhfUpdateGuildIcon + handlerTable[network.MSG_MHF_CREATE_JOINT] = HandleMsgMhfCreateJoint + handlerTable[network.MSG_MHF_OPERATE_JOINT] = HandleMsgMhfOperateJoint + handlerTable[network.MSG_MHF_INFO_JOINT] = HandleMsgMhfInfoJoint + handlerTable[network.MSG_MHF_UPDATE_GUILD_ICON] = HandleMsgMhfUpdateGuildIcon handlerTable[network.MSG_MHF_INFO_FESTA] = handleMsgMhfInfoFesta handlerTable[network.MSG_MHF_ENTRY_FESTA] = handleMsgMhfEntryFesta handlerTable[network.MSG_MHF_CHARGE_FESTA] = handleMsgMhfChargeFesta @@ -207,8 +207,8 @@ func init() { handlerTable[network.MSG_MHF_UPDATE_CAFEPOINT] = handleMsgMhfUpdateCafepoint handlerTable[network.MSG_MHF_CHECK_DAILY_CAFEPOINT] = handleMsgMhfCheckDailyCafepoint handlerTable[network.MSG_MHF_GET_COG_INFO] = handleMsgMhfGetCogInfo - handlerTable[network.MSG_MHF_CHECK_MONTHLY_ITEM] = handleMsgMhfCheckMonthlyItem - handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_ITEM] = handleMsgMhfAcquireMonthlyItem + handlerTable[network.MSG_MHF_CHECK_MONTHLY_ITEM] = HandleMsgMhfCheckMonthlyItem + handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_ITEM] = HandleMsgMhfAcquireMonthlyItem handlerTable[network.MSG_MHF_CHECK_WEEKLY_STAMP] = handleMsgMhfCheckWeeklyStamp handlerTable[network.MSG_MHF_EXCHANGE_WEEKLY_STAMP] = handleMsgMhfExchangeWeeklyStamp handlerTable[network.MSG_MHF_CREATE_MERCENARY] = handleMsgMhfCreateMercenary @@ -238,8 +238,8 @@ func init() { handlerTable[network.MSG_MHF_GET_MYHOUSE_INFO] = handleMsgMhfGetMyhouseInfo handlerTable[network.MSG_MHF_UPDATE_MYHOUSE_INFO] = handleMsgMhfUpdateMyhouseInfo handlerTable[network.MSG_MHF_GET_WEEKLY_SCHEDULE] = handleMsgMhfGetWeeklySchedule - handlerTable[network.MSG_MHF_ENUMERATE_INV_GUILD] = handleMsgMhfEnumerateInvGuild - handlerTable[network.MSG_MHF_OPERATION_INV_GUILD] = handleMsgMhfOperationInvGuild + handlerTable[network.MSG_MHF_ENUMERATE_INV_GUILD] = HandleMsgMhfEnumerateInvGuild + handlerTable[network.MSG_MHF_OPERATION_INV_GUILD] = HandleMsgMhfOperationInvGuild handlerTable[network.MSG_MHF_STAMPCARD_STAMP] = handleMsgMhfStampcardStamp handlerTable[network.MSG_MHF_STAMPCARD_PRIZE] = handleMsgMhfStampcardPrize handlerTable[network.MSG_MHF_UNRESERVE_SRG] = handleMsgMhfUnreserveSrg @@ -247,8 +247,8 @@ func init() { handlerTable[network.MSG_MHF_SAVE_PLATE_DATA] = handleMsgMhfSavePlateData handlerTable[network.MSG_MHF_LOAD_PLATE_BOX] = handleMsgMhfLoadPlateBox handlerTable[network.MSG_MHF_SAVE_PLATE_BOX] = handleMsgMhfSavePlateBox - handlerTable[network.MSG_MHF_READ_GUILDCARD] = handleMsgMhfReadGuildcard - handlerTable[network.MSG_MHF_UPDATE_GUILDCARD] = handleMsgMhfUpdateGuildcard + handlerTable[network.MSG_MHF_READ_GUILDCARD] = HandleMsgMhfReadGuildcard + handlerTable[network.MSG_MHF_UPDATE_GUILDCARD] = HandleMsgMhfUpdateGuildcard handlerTable[network.MSG_MHF_READ_BEAT_LEVEL] = handleMsgMhfReadBeatLevel handlerTable[network.MSG_MHF_UPDATE_BEAT_LEVEL] = handleMsgMhfUpdateBeatLevel handlerTable[network.MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING] = handleMsgMhfReadBeatLevelAllRanking @@ -264,38 +264,38 @@ func init() { handlerTable[network.MSG_MHF_GET_EARTH_STATUS] = handleMsgMhfGetEarthStatus handlerTable[network.MSG_MHF_LOAD_PARTNER] = handleMsgMhfLoadPartner handlerTable[network.MSG_MHF_SAVE_PARTNER] = handleMsgMhfSavePartner - handlerTable[network.MSG_MHF_GET_GUILD_MISSION_LIST] = handleMsgMhfGetGuildMissionList - handlerTable[network.MSG_MHF_GET_GUILD_MISSION_RECORD] = handleMsgMhfGetGuildMissionRecord - handlerTable[network.MSG_MHF_ADD_GUILD_MISSION_COUNT] = handleMsgMhfAddGuildMissionCount - handlerTable[network.MSG_MHF_SET_GUILD_MISSION_TARGET] = handleMsgMhfSetGuildMissionTarget - handlerTable[network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET] = handleMsgMhfCancelGuildMissionTarget + handlerTable[network.MSG_MHF_GET_GUILD_MISSION_LIST] = HandleMsgMhfGetGuildMissionList + handlerTable[network.MSG_MHF_GET_GUILD_MISSION_RECORD] = HandleMsgMhfGetGuildMissionRecord + handlerTable[network.MSG_MHF_ADD_GUILD_MISSION_COUNT] = HandleMsgMhfAddGuildMissionCount + handlerTable[network.MSG_MHF_SET_GUILD_MISSION_TARGET] = HandleMsgMhfSetGuildMissionTarget + handlerTable[network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET] = HandleMsgMhfCancelGuildMissionTarget handlerTable[network.MSG_MHF_LOAD_OTOMO_AIROU] = handleMsgMhfLoadOtomoAirou handlerTable[network.MSG_MHF_SAVE_OTOMO_AIROU] = handleMsgMhfSaveOtomoAirou - handlerTable[network.MSG_MHF_ENUMERATE_GUILD_TRESURE] = handleMsgMhfEnumerateGuildTresure + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_TRESURE] = HandleMsgMhfEnumerateGuildTresure handlerTable[network.MSG_MHF_ENUMERATE_AIROULIST] = handleMsgMhfEnumerateAiroulist - handlerTable[network.MSG_MHF_REGIST_GUILD_TRESURE] = handleMsgMhfRegistGuildTresure - handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE] = handleMsgMhfAcquireGuildTresure - handlerTable[network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT] = handleMsgMhfOperateGuildTresureReport - handlerTable[network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR] = handleMsgMhfGetGuildTresureSouvenir - handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR] = handleMsgMhfAcquireGuildTresureSouvenir + handlerTable[network.MSG_MHF_REGIST_GUILD_TRESURE] = HandleMsgMhfRegistGuildTresure + handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE] = HandleMsgMhfAcquireGuildTresure + handlerTable[network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT] = HandleMsgMhfOperateGuildTresureReport + handlerTable[network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR] = HandleMsgMhfGetGuildTresureSouvenir + handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR] = HandleMsgMhfAcquireGuildTresureSouvenir handlerTable[network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE] = handleMsgMhfEnumerateFestaIntermediatePrize handlerTable[network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE] = handleMsgMhfAcquireFestaIntermediatePrize handlerTable[network.MSG_MHF_LOAD_DECO_MYSET] = handleMsgMhfLoadDecoMyset handlerTable[network.MSG_MHF_SAVE_DECO_MYSET] = handleMsgMhfSaveDecoMyset handlerTable[network.MSG_MHF_reserve10F] = handleMsgMhfReserve10F - handlerTable[network.MSG_MHF_LOAD_GUILD_COOKING] = handleMsgMhfLoadGuildCooking - handlerTable[network.MSG_MHF_REGIST_GUILD_COOKING] = handleMsgMhfRegistGuildCooking - handlerTable[network.MSG_MHF_LOAD_GUILD_ADVENTURE] = handleMsgMhfLoadGuildAdventure - handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE] = handleMsgMhfRegistGuildAdventure - handlerTable[network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE] = handleMsgMhfAcquireGuildAdventure - handlerTable[network.MSG_MHF_CHARGE_GUILD_ADVENTURE] = handleMsgMhfChargeGuildAdventure + handlerTable[network.MSG_MHF_LOAD_GUILD_COOKING] = HandleMsgMhfLoadGuildCooking + handlerTable[network.MSG_MHF_REGIST_GUILD_COOKING] = HandleMsgMhfRegistGuildCooking + handlerTable[network.MSG_MHF_LOAD_GUILD_ADVENTURE] = HandleMsgMhfLoadGuildAdventure + handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE] = HandleMsgMhfRegistGuildAdventure + handlerTable[network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE] = HandleMsgMhfAcquireGuildAdventure + handlerTable[network.MSG_MHF_CHARGE_GUILD_ADVENTURE] = HandleMsgMhfChargeGuildAdventure handlerTable[network.MSG_MHF_LOAD_LEGEND_DISPATCH] = handleMsgMhfLoadLegendDispatch handlerTable[network.MSG_MHF_LOAD_HUNTER_NAVI] = handleMsgMhfLoadHunterNavi handlerTable[network.MSG_MHF_SAVE_HUNTER_NAVI] = handleMsgMhfSaveHunterNavi handlerTable[network.MSG_MHF_REGIST_SPABI_TIME] = handleMsgMhfRegistSpabiTime - handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER] = handleMsgMhfGetGuildWeeklyBonusMaster - handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT] = handleMsgMhfGetGuildWeeklyBonusActiveCount - handlerTable[network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER] = handleMsgMhfAddGuildWeeklyBonusExceptionalUser + handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER] = HandleMsgMhfGetGuildWeeklyBonusMaster + handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT] = HandleMsgMhfGetGuildWeeklyBonusActiveCount + handlerTable[network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER] = HandleMsgMhfAddGuildWeeklyBonusExceptionalUser handlerTable[network.MSG_MHF_GET_TOWER_INFO] = handleMsgMhfGetTowerInfo handlerTable[network.MSG_MHF_POST_TOWER_INFO] = handleMsgMhfPostTowerInfo handlerTable[network.MSG_MHF_GET_GEM_INFO] = handleMsgMhfGetGemInfo @@ -328,7 +328,7 @@ func init() { handlerTable[network.MSG_MHF_GET_TINY_BIN] = handleMsgMhfGetTinyBin handlerTable[network.MSG_MHF_POST_TINY_BIN] = handleMsgMhfPostTinyBin handlerTable[network.MSG_MHF_GET_SENYU_DAILY_COUNT] = handleMsgMhfGetSenyuDailyCount - handlerTable[network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM] = handleMsgMhfGetGuildTargetMemberNum + handlerTable[network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM] = HandleMsgMhfGetGuildTargetMemberNum handlerTable[network.MSG_MHF_GET_BOOST_RIGHT] = handleMsgMhfGetBoostRight handlerTable[network.MSG_MHF_START_BOOST_TIME] = handleMsgMhfStartBoostTime handlerTable[network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN] = handleMsgMhfPostBoostTimeQuestReturn @@ -341,19 +341,19 @@ func init() { handlerTable[network.MSG_MHF_POST_RYOUDAMA] = handleMsgMhfPostRyoudama handlerTable[network.MSG_MHF_GET_TENROUIRAI] = handleMsgMhfGetTenrouirai handlerTable[network.MSG_MHF_POST_TENROUIRAI] = handleMsgMhfPostTenrouirai - handlerTable[network.MSG_MHF_POST_GUILD_SCOUT] = handleMsgMhfPostGuildScout - handlerTable[network.MSG_MHF_CANCEL_GUILD_SCOUT] = handleMsgMhfCancelGuildScout - handlerTable[network.MSG_MHF_ANSWER_GUILD_SCOUT] = handleMsgMhfAnswerGuildScout - handlerTable[network.MSG_MHF_GET_GUILD_SCOUT_LIST] = handleMsgMhfGetGuildScoutList - handlerTable[network.MSG_MHF_GET_GUILD_MANAGE_RIGHT] = handleMsgMhfGetGuildManageRight - handlerTable[network.MSG_MHF_SET_GUILD_MANAGE_RIGHT] = handleMsgMhfSetGuildManageRight + handlerTable[network.MSG_MHF_POST_GUILD_SCOUT] = HandleMsgMhfPostGuildScout + handlerTable[network.MSG_MHF_CANCEL_GUILD_SCOUT] = HandleMsgMhfCancelGuildScout + handlerTable[network.MSG_MHF_ANSWER_GUILD_SCOUT] = HandleMsgMhfAnswerGuildScout + handlerTable[network.MSG_MHF_GET_GUILD_SCOUT_LIST] = HandleMsgMhfGetGuildScoutList + handlerTable[network.MSG_MHF_GET_GUILD_MANAGE_RIGHT] = HandleMsgMhfGetGuildManageRight + handlerTable[network.MSG_MHF_SET_GUILD_MANAGE_RIGHT] = HandleMsgMhfSetGuildManageRight handlerTable[network.MSG_MHF_PLAY_NORMAL_GACHA] = handleMsgMhfPlayNormalGacha handlerTable[network.MSG_MHF_GET_DAILY_MISSION_MASTER] = handleMsgMhfGetDailyMissionMaster handlerTable[network.MSG_MHF_GET_DAILY_MISSION_PERSONAL] = handleMsgMhfGetDailyMissionPersonal handlerTable[network.MSG_MHF_SET_DAILY_MISSION_PERSONAL] = handleMsgMhfSetDailyMissionPersonal handlerTable[network.MSG_MHF_GET_GACHA_PLAY_HISTORY] = handleMsgMhfGetGachaPlayHistory - handlerTable[network.MSG_MHF_GET_REJECT_GUILD_SCOUT] = handleMsgMhfGetRejectGuildScout - handlerTable[network.MSG_MHF_SET_REJECT_GUILD_SCOUT] = handleMsgMhfSetRejectGuildScout + handlerTable[network.MSG_MHF_GET_REJECT_GUILD_SCOUT] = HandleMsgMhfGetRejectGuildScout + handlerTable[network.MSG_MHF_SET_REJECT_GUILD_SCOUT] = HandleMsgMhfSetRejectGuildScout handlerTable[network.MSG_MHF_GET_CA_ACHIEVEMENT_HIST] = handleMsgMhfGetCaAchievementHist handlerTable[network.MSG_MHF_SET_CA_ACHIEVEMENT_HIST] = handleMsgMhfSetCaAchievementHist handlerTable[network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS] = handleMsgMhfGetKeepLoginBoostStatus @@ -378,8 +378,8 @@ func init() { handlerTable[network.MSG_MHF_GET_UD_RANKING] = handleMsgMhfGetUdRanking handlerTable[network.MSG_MHF_GET_UD_MY_RANKING] = handleMsgMhfGetUdMyRanking handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_REWARD] = handleMsgMhfAcquireMonthlyReward - handlerTable[network.MSG_MHF_GET_UD_GUILD_MAP_INFO] = handleMsgMhfGetUdGuildMapInfo - handlerTable[network.MSG_MHF_GENERATE_UD_GUILD_MAP] = handleMsgMhfGenerateUdGuildMap + handlerTable[network.MSG_MHF_GET_UD_GUILD_MAP_INFO] = HandleMsgMhfGetUdGuildMapInfo + handlerTable[network.MSG_MHF_GENERATE_UD_GUILD_MAP] = HandleMsgMhfGenerateUdGuildMap handlerTable[network.MSG_MHF_GET_UD_TACTICS_POINT] = handleMsgMhfGetUdTacticsPoint handlerTable[network.MSG_MHF_ADD_UD_TACTICS_POINT] = handleMsgMhfAddUdTacticsPoint handlerTable[network.MSG_MHF_GET_UD_TACTICS_RANKING] = handleMsgMhfGetUdTacticsRanking @@ -396,7 +396,7 @@ func init() { handlerTable[network.MSG_MHF_SEX_CHANGER] = handleMsgMhfSexChanger handlerTable[network.MSG_MHF_GET_LOBBY_CROWD] = handleMsgMhfGetLobbyCrowd handlerTable[network.MSG_SYS_reserve180] = handleMsgSysReserve180 - handlerTable[network.MSG_MHF_GUILD_HUNTDATA] = handleMsgMhfGuildHuntdata + handlerTable[network.MSG_MHF_GUILD_HUNTDATA] = HandleMsgMhfGuildHuntdata handlerTable[network.MSG_MHF_ADD_KOURYOU_POINT] = handleMsgMhfAddKouryouPoint handlerTable[network.MSG_MHF_GET_KOURYOU_POINT] = handleMsgMhfGetKouryouPoint handlerTable[network.MSG_MHF_EXCHANGE_KOURYOU_POINT] = handleMsgMhfExchangeKouryouPoint @@ -427,12 +427,12 @@ func init() { handlerTable[network.MSG_MHF_LOAD_MEZFES_DATA] = handleMsgMhfLoadMezfesData handlerTable[network.MSG_SYS_reserve19E] = handleMsgSysReserve19E handlerTable[network.MSG_SYS_reserve19F] = handleMsgSysReserve19F - handlerTable[network.MSG_MHF_UPDATE_FORCE_GUILD_RANK] = handleMsgMhfUpdateForceGuildRank + handlerTable[network.MSG_MHF_UPDATE_FORCE_GUILD_RANK] = HandleMsgMhfUpdateForceGuildRank handlerTable[network.MSG_MHF_RESET_TITLE] = handleMsgMhfResetTitle - handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD] = handleMsgMhfEnumerateGuildMessageBoard - handlerTable[network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD] = handleMsgMhfUpdateGuildMessageBoard + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD] = HandleMsgMhfEnumerateGuildMessageBoard + handlerTable[network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD] = HandleMsgMhfUpdateGuildMessageBoard handlerTable[network.MSG_SYS_reserve1A4] = handleMsgSysReserve1A4 - handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE_DIVA] = handleMsgMhfRegistGuildAdventureDiva + handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE_DIVA] = HandleMsgMhfRegistGuildAdventureDiva handlerTable[network.MSG_SYS_reserve1A6] = handleMsgSysReserve1A6 handlerTable[network.MSG_SYS_reserve1A7] = handleMsgSysReserve1A7 handlerTable[network.MSG_SYS_reserve1A8] = handleMsgSysReserve1A8 diff --git a/server/channelserver/sys_language.go b/server/channelserver/sys_language.go index 5fb423d99..d1a3dfccf 100644 --- a/server/channelserver/sys_language.go +++ b/server/channelserver/sys_language.go @@ -1,5 +1,9 @@ package channelserver +import ( + "erupe-ce/config" +) + type i18n struct { language string cafe struct { @@ -101,9 +105,9 @@ type i18n struct { } } -func getLangStrings(server *Server) i18n { +func getLangStrings(server *ChannelServer) i18n { var i i18n - switch server.erupeConfig.Language { + switch config.GetConfig().Language { case "jp": i.language = "日本語" i.cafe.reset = "%d/%dにリセット" diff --git a/server/channelserver/sys_ravi.go b/server/channelserver/sys_ravi.go index 83dcbcbb8..e1089d90a 100644 --- a/server/channelserver/sys_ravi.go +++ b/server/channelserver/sys_ravi.go @@ -13,7 +13,7 @@ type Raviente struct { support []uint32 } -func (server *Server) resetRaviente() { +func (server *ChannelServer) resetRaviente() { for _, semaphore := range server.semaphore { if strings.HasPrefix(semaphore.name, "hs_l0") { return @@ -26,7 +26,7 @@ func (server *Server) resetRaviente() { server.raviente.support = make([]uint32, 30) } -func (server *Server) GetRaviMultiplier() float64 { +func (server *ChannelServer) GetRaviMultiplier() float64 { raviSema := server.getRaviSemaphore() if raviSema != nil { var minPlayers int @@ -43,7 +43,7 @@ func (server *Server) GetRaviMultiplier() float64 { return 0 } -func (server *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) { +func (server *ChannelServer) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) { var prev uint32 var dest *[]uint32 switch semaID { diff --git a/server/channelserver/sys_session.go b/server/channelserver/sys_session.go index fe6c10ba4..311acdac3 100644 --- a/server/channelserver/sys_session.go +++ b/server/channelserver/sys_session.go @@ -3,29 +3,29 @@ package channelserver import ( "encoding/binary" "encoding/hex" - _config "erupe-ce/config" + "erupe-ce/config" + "erupe-ce/network" + "erupe-ce/network/mhfpacket" + "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" + "erupe-ce/utils/logger" "erupe-ce/utils/mhfcourse" + "erupe-ce/utils/stringstack" "fmt" "io" "net" "sync" "time" - "erupe-ce/network" - "erupe-ce/network/mhfpacket" - "erupe-ce/utils/byteframe" - "erupe-ce/utils/logger" - "erupe-ce/utils/stringstack" - "go.uber.org/zap" ) // Session holds state for the channel server connection. type Session struct { sync.Mutex - logger logger.Logger - server *Server + Logger logger.Logger + Server *ChannelServer rawConn net.Conn cryptConn *network.CryptConn sendPackets chan mhfpacket.MHFPacket @@ -37,7 +37,7 @@ type Session struct { reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet. stagePass string // Temporary storage prevGuildID uint32 // Stores the last GuildID used in InfoGuild - charID uint32 + CharID uint32 logKey []byte sessionStart int64 courses []mhfcourse.Course @@ -66,10 +66,10 @@ type Session struct { } // NewSession creates a new Session type. -func NewSession(server *Server, conn net.Conn) *Session { +func NewSession(server *ChannelServer, conn net.Conn) *Session { s := &Session{ - logger: server.logger.Named(conn.RemoteAddr().String()), - server: server, + Logger: server.logger.Named(conn.RemoteAddr().String()), + Server: server, rawConn: conn, cryptConn: network.NewCryptConn(conn), sendPackets: make(chan mhfpacket.MHFPacket, 20), @@ -85,7 +85,7 @@ func NewSession(server *Server, conn net.Conn) *Session { // Start starts the session packet send and recv loop(s). func (s *Session) Start() { - s.logger.Debug("New connection", zap.String("RemoteAddr", s.rawConn.RemoteAddr().String())) + s.Logger.Debug("New connection", zap.String("RemoteAddr", s.rawConn.RemoteAddr().String())) // Unlike the sign and entrance server, // the client DOES NOT initalize the channel connection with 8 NULL bytes. go s.sendLoop() @@ -97,7 +97,7 @@ func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) { select { case s.sendPackets <- pkt: default: - s.logger.Warn("Packet queue too full, dropping!") + s.Logger.Warn("Packet queue too full, dropping!") } } @@ -123,11 +123,11 @@ func (s *Session) sendLoop() { if len(buffer) > 0 { err := s.cryptConn.SendPacket(buffer) if err != nil { - s.logger.Warn("Failed to send packet") + s.Logger.Warn("Failed to send packet") } buffer = buffer[:0] } - time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond) + time.Sleep(time.Duration(config.GetConfig().LoopDelay) * time.Millisecond) } } @@ -143,16 +143,16 @@ func (s *Session) recvLoop() { } pkt, err := s.cryptConn.ReadPacket() if err == io.EOF { - s.logger.Info(fmt.Sprintf("[%s] Disconnected", s.Name)) + s.Logger.Info(fmt.Sprintf("[%s] Disconnected", s.Name)) logoutPlayer(s) return } else if err != nil { - s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err)) + s.Logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err)) logoutPlayer(s) return } s.handlePacketGroup(pkt) - time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond) + time.Sleep(time.Duration(config.GetConfig().LoopDelay) * time.Millisecond) } } @@ -220,9 +220,9 @@ func ignored(opcode network.PacketID) bool { } func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipient string) { - if sender == "Server" && !s.server.erupeConfig.DebugOptions.LogOutboundMessages { + if sender == "Server" && !config.GetConfig().DebugOptions.LogOutboundMessages { return - } else if sender != "Server" && !s.server.erupeConfig.DebugOptions.LogInboundMessages { + } else if sender != "Server" && !config.GetConfig().DebugOptions.LogInboundMessages { return } @@ -240,8 +240,8 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien fmt.Printf("[%s] -> [%s]\n", sender, recipient) } fmt.Printf("Opcode: (Dec: %d Hex: 0x%04X Name: %s) \n", opcode, opcode, opcodePID) - if s.server.erupeConfig.DebugOptions.LogMessageData { - if len(data) <= s.server.erupeConfig.DebugOptions.MaxHexdumpLength { + if config.GetConfig().DebugOptions.LogMessageData { + if len(data) <= config.GetConfig().DebugOptions.MaxHexdumpLength { fmt.Printf("Data [%d bytes]:\n%s\n", len(data), hex.Dump(data)) } else { fmt.Printf("Data [%d bytes]: (Too long!)\n\n", len(data)) @@ -254,23 +254,23 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien func (s *Session) SetObjectID() { for i := uint16(1); i < 127; i++ { exists := false - for _, j := range s.server.objectIDs { + for _, j := range s.Server.objectIDs { if i == j { exists = true break } } if !exists { - s.server.objectIDs[s] = i + s.Server.objectIDs[s] = i return } } - s.server.objectIDs[s] = 0 + s.Server.objectIDs[s] = 0 } func (s *Session) NextObjectID() uint32 { bf := byteframe.NewByteFrame() - bf.WriteUint16(s.server.objectIDs[s]) + bf.WriteUint16(s.Server.objectIDs[s]) s.objectIndex++ bf.WriteUint16(s.objectIndex) bf.Seek(0, 0) @@ -287,7 +287,11 @@ func (s *Session) GetSemaphoreID() uint32 { func (s *Session) isOp() bool { var op bool - err := s.server.db.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&op) + database, err := db.GetDB() + if err != nil { + s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&op) if err == nil && op { return true } diff --git a/server/discordbot/discord_bot.go b/server/discordbot/discord_bot.go index 6cdd39afa..f0f657207 100644 --- a/server/discordbot/discord_bot.go +++ b/server/discordbot/discord_bot.go @@ -1,7 +1,7 @@ package discordbot import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/utils/logger" "regexp" @@ -38,18 +38,14 @@ var Commands = []*discordgo.ApplicationCommand{ type DiscordBot struct { Session *discordgo.Session - config *_config.Config + config *config.Config logger logger.Logger MainGuild *discordgo.Guild RelayChannel *discordgo.Channel } -type Options struct { - Config *_config.Config -} - -func NewDiscordBot(options Options) (discordBot *DiscordBot, err error) { - session, err := discordgo.New("Bot " + options.Config.Discord.BotToken) +func NewDiscordBot() (discordBot *DiscordBot, err error) { + session, err := discordgo.New("Bot " + config.GetConfig().Discord.BotToken) discordLogger := logger.Get().Named("discord") if err != nil { discordLogger.Fatal("Discord failed", zap.Error(err)) @@ -58,8 +54,8 @@ func NewDiscordBot(options Options) (discordBot *DiscordBot, err error) { var relayChannel *discordgo.Channel - if options.Config.Discord.RelayChannel.Enabled { - relayChannel, err = session.Channel(options.Config.Discord.RelayChannel.RelayChannelID) + if config.GetConfig().Discord.RelayChannel.Enabled { + relayChannel, err = session.Channel(config.GetConfig().Discord.RelayChannel.RelayChannelID) } if err != nil { @@ -68,7 +64,7 @@ func NewDiscordBot(options Options) (discordBot *DiscordBot, err error) { } discordBot = &DiscordBot{ - config: options.Config, + config: config.GetConfig(), logger: discordLogger, Session: session, RelayChannel: relayChannel, diff --git a/server/entranceserver/entrance_server.go b/server/entrance/entrance_server.go similarity index 71% rename from server/entranceserver/entrance_server.go rename to server/entrance/entrance_server.go index b9374f562..fbce030d2 100644 --- a/server/entranceserver/entrance_server.go +++ b/server/entrance/entrance_server.go @@ -1,4 +1,4 @@ -package entranceserver +package entrance import ( "encoding/hex" @@ -8,45 +8,33 @@ import ( "strings" "sync" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/logger" - "github.com/jmoiron/sqlx" "go.uber.org/zap" ) -// Server is a MHF entrance server. -type Server struct { +// EntranceServer is a MHF entrance server. +type EntranceServer struct { sync.Mutex logger logger.Logger - erupeConfig *_config.Config - db *sqlx.DB listener net.Listener isShuttingDown bool } -// Config struct allows configuring the server. -type Config struct { - Logger logger.Logger - DB *sqlx.DB - ErupeConfig *_config.Config -} - // NewServer creates a new Server type. -func NewServer(config *Config) *Server { - server := &Server{ - logger: config.Logger, - erupeConfig: config.ErupeConfig, - db: config.DB, +func NewServer() *EntranceServer { + server := &EntranceServer{ + logger: logger.Get().Named("entrance"), } return server } // Start starts the server in a new goroutine. -func (server *Server) Start() error { +func (server *EntranceServer) Start() error { - l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.erupeConfig.Entrance.Port)) + l, err := net.Listen("tcp", fmt.Sprintf(":%d", config.GetConfig().Entrance.Port)) if err != nil { return err } @@ -59,7 +47,7 @@ func (server *Server) Start() error { } // Shutdown exits the server gracefully. -func (server *Server) Shutdown() { +func (server *EntranceServer) Shutdown() { server.logger.Debug("Shutting down...") server.Lock() @@ -71,7 +59,7 @@ func (server *Server) Shutdown() { } // acceptClients handles accepting new clients in a loop. -func (server *Server) acceptClients() { +func (server *EntranceServer) acceptClients() { for { conn, err := server.listener.Accept() if err != nil { @@ -92,7 +80,7 @@ func (server *Server) acceptClients() { } } -func (server *Server) handleEntranceServerConnection(conn net.Conn) { +func (server *EntranceServer) handleEntranceServerConnection(conn net.Conn) { defer conn.Close() // Client initalizes the connection with a one-time buffer of 8 NULL bytes. nullInit := make([]byte, 8) @@ -113,7 +101,7 @@ func (server *Server) handleEntranceServerConnection(conn net.Conn) { return } - if server.erupeConfig.DebugOptions.LogInboundMessages { + if config.GetConfig().DebugOptions.LogInboundMessages { fmt.Printf("[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt)) } @@ -121,7 +109,7 @@ func (server *Server) handleEntranceServerConnection(conn net.Conn) { if strings.Split(conn.RemoteAddr().String(), ":")[0] == "127.0.0.1" { local = true } - data := makeSv2Resp(server.erupeConfig, server, local) + data := makeSv2Resp(server, local) if len(pkt) > 5 { data = append(data, makeUsrResp(pkt, server)...) } diff --git a/server/entranceserver/make_resp.go b/server/entrance/make_resp.go similarity index 64% rename from server/entranceserver/make_resp.go rename to server/entrance/make_resp.go index 53373701d..08a640e45 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entrance/make_resp.go @@ -1,39 +1,41 @@ -package entranceserver +package entrance import ( "encoding/binary" "encoding/hex" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network/crypto/bin8" "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" + "erupe-ce/utils/stringsupport" "fmt" "net" ) -func encodeServerInfo(config *_config.Config, server *Server, local bool) []byte { - serverInfos := config.Entrance.Entries +func encodeServerInfo(server *EntranceServer, local bool) []byte { + serverInfos := config.GetConfig().Entrance.Entries bf := byteframe.NewByteFrame() for serverIdx, si := range serverInfos { // Prevent MezFes Worlds displaying on Z1 - if config.ClientID <= _config.Z1 { + if config.GetConfig().ClientID <= config.Z1 { if si.Type == 6 { continue } } - if config.ClientID <= _config.G6 { + if config.GetConfig().ClientID <= config.G6 { if si.Type == 5 { continue } } if si.IP == "" { - si.IP = config.Host + si.IP = config.GetConfig().Host } if local { - bf.WriteUint32(0x0100007F) // 127.0.0.1 + bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP("127.0.0.1").To4())) } else { bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(si.IP).To4())) } @@ -42,36 +44,40 @@ func encodeServerInfo(config *_config.Config, server *Server, local bool) []byte bf.WriteUint16(uint16(len(si.Channels))) bf.WriteUint8(si.Type) bf.WriteUint8(uint8(((gametime.TimeAdjusted().Unix() / 86400) + int64(serverIdx)) % 3)) - if server.erupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { bf.WriteUint8(si.Recommended) } fullName := append(append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...), stringsupport.UTF8ToSJIS(si.Description)...) - if server.erupeConfig.ClientID >= _config.G1 && server.erupeConfig.ClientID <= _config.G5 { + if config.GetConfig().ClientID >= config.G1 && config.GetConfig().ClientID <= config.G5 { bf.WriteUint8(uint8(len(fullName))) bf.WriteBytes(fullName) } else { - if server.erupeConfig.ClientID >= _config.G51 { + if config.GetConfig().ClientID >= config.G51 { bf.WriteUint8(0) // Ignored } bf.WriteBytes(stringsupport.PaddedString(string(fullName), 65, false)) } - if server.erupeConfig.ClientID >= _config.GG { + if config.GetConfig().ClientID >= config.GG { bf.WriteUint32(si.AllowedClientFlags) } for channelIdx, ci := range si.Channels { sid := (serverIdx<<8 | 4096) + (channelIdx | 16) - if _config.ErupeConfig.DebugOptions.ProxyPort != 0 { - bf.WriteUint16(_config.ErupeConfig.DebugOptions.ProxyPort) + if config.GetConfig().DebugOptions.ProxyPort != 0 { + bf.WriteUint16(config.GetConfig().DebugOptions.ProxyPort) } else { bf.WriteUint16(ci.Port) } bf.WriteUint16(uint16(channelIdx | 16)) bf.WriteUint16(ci.MaxPlayers) var currentPlayers uint16 - server.db.QueryRow("SELECT current_players FROM servers WHERE server_id=$1", sid).Scan(¤tPlayers) + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + database.QueryRow("SELECT current_players FROM servers WHERE server_id=$1", sid).Scan(¤tPlayers) bf.WriteUint16(currentPlayers) bf.WriteUint16(0) bf.WriteUint16(0) @@ -86,7 +92,7 @@ func encodeServerInfo(config *_config.Config, server *Server, local bool) []byte } } bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) - bf.WriteUint32(uint32(server.erupeConfig.GameplayOptions.ClanMemberLimits[len(server.erupeConfig.GameplayOptions.ClanMemberLimits)-1][1])) + bf.WriteUint32(uint32(config.GetConfig().GameplayOptions.ClanMemberLimits[len(config.GetConfig().GameplayOptions.ClanMemberLimits)-1][1])) return bf.Data() } @@ -108,11 +114,11 @@ func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byt return bf.Data() } -func makeSv2Resp(config *_config.Config, server *Server, local bool) []byte { - serverInfos := config.Entrance.Entries +func makeSv2Resp(server *EntranceServer, local bool) []byte { + serverInfos := config.GetConfig().Entrance.Entries // Decrease by the number of MezFes Worlds var mf int - if config.ClientID <= _config.Z1 { + if config.GetConfig().ClientID <= config.Z1 { for _, si := range serverInfos { if si.Type == 6 { mf++ @@ -121,21 +127,21 @@ func makeSv2Resp(config *_config.Config, server *Server, local bool) []byte { } // and Return Worlds var ret int - if config.ClientID <= _config.G6 { + if config.GetConfig().ClientID <= config.G6 { for _, si := range serverInfos { if si.Type == 5 { ret++ } } } - rawServerData := encodeServerInfo(config, server, local) + rawServerData := encodeServerInfo(server, local) - if server.erupeConfig.DebugOptions.LogOutboundMessages { + if config.GetConfig().DebugOptions.LogOutboundMessages { fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(rawServerData), hex.Dump(rawServerData)) } respType := "SV2" - if config.ClientID <= _config.G32 { + if config.GetConfig().ClientID <= config.G32 { respType = "SVR" } @@ -144,16 +150,20 @@ func makeSv2Resp(config *_config.Config, server *Server, local bool) []byte { return bf.Data() } -func makeUsrResp(pkt []byte, server *Server) []byte { +func makeUsrResp(pkt []byte, server *EntranceServer) []byte { bf := byteframe.NewByteFrameFromBytes(pkt) _ = bf.ReadUint32() // ALL+ _ = bf.ReadUint8() // 0x00 userEntries := bf.ReadUint16() resp := byteframe.NewByteFrame() + database, err := db.GetDB() + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } for i := 0; i < int(userEntries); i++ { cid := bf.ReadUint32() var sid uint16 - err := server.db.QueryRow("SELECT(SELECT server_id FROM sign_sessions WHERE char_id=$1) AS _", cid).Scan(&sid) + err := database.QueryRow("SELECT(SELECT server_id FROM sign_sessions WHERE char_id=$1) AS _", cid).Scan(&sid) if err != nil { resp.WriteUint16(0) } else { @@ -162,7 +172,7 @@ func makeUsrResp(pkt []byte, server *Server) []byte { resp.WriteUint16(0) } - if server.erupeConfig.DebugOptions.LogOutboundMessages { + if config.GetConfig().DebugOptions.LogOutboundMessages { fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(resp.Data()), hex.Dump(resp.Data())) } diff --git a/server/sign/dbutils.go b/server/sign/dbutils.go new file mode 100644 index 000000000..4af86c7ef --- /dev/null +++ b/server/sign/dbutils.go @@ -0,0 +1,318 @@ +package sign + +import ( + "database/sql" + "errors" + "erupe-ce/config" + "erupe-ce/utils/db" + "erupe-ce/utils/mhfcourse" + "erupe-ce/utils/token" + "fmt" + "strings" + "time" + + "go.uber.org/zap" + "golang.org/x/crypto/bcrypt" +) + +func (server *SignServer) newUserChara(uid uint32) error { + var numNewChars int + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow("SELECT COUNT(*) FROM characters WHERE user_id = $1 AND is_new_character = true", uid).Scan(&numNewChars) + if err != nil { + return err + } + + // prevent users with an uninitialised character from creating more + if numNewChars >= 1 { + return err + } + + _, err = database.Exec(` + INSERT INTO characters ( + user_id, is_female, is_new_character, name, unk_desc_string, + hr, gr, weapon_type, last_login) + VALUES($1, False, True, '', '', 0, 0, 0, $2)`, + uid, + uint32(time.Now().Unix()), + ) + if err != nil { + return err + } + + return nil +} + +func (server *SignServer) registerDBAccount(username string, password string) (uint32, error) { + var uid uint32 + server.logger.Info("Creating user", zap.String("User", username)) + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + // Create salted hash of user password + passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return 0, err + } + + err = database.QueryRow("INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3) RETURNING id", username, string(passwordHash), time.Now().Add(time.Hour*24*30)).Scan(&uid) + if err != nil { + return 0, err + } + + return uid, nil +} + +type character struct { + ID uint32 `db:"id"` + IsFemale bool `db:"is_female"` + IsNewCharacter bool `db:"is_new_character"` + Name string `db:"name"` + UnkDescString string `db:"unk_desc_string"` + HR uint16 `db:"hr"` + GR uint16 `db:"gr"` + WeaponType uint16 `db:"weapon_type"` + LastLogin uint32 `db:"last_login"` +} + +func (server *SignServer) getCharactersForUser(uid uint32) ([]character, error) { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + characters := make([]character, 0) + err = database.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hr, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY id", uid) + if err != nil { + return nil, err + } + return characters, nil +} + +func (server *SignServer) getReturnExpiry(uid uint32) time.Time { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var returnExpiry, lastLogin time.Time + database.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid) + if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) { + returnExpiry = time.Now().Add(time.Hour * 24 * 30) + database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) + } else { + err := database.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid) + if err != nil { + returnExpiry = time.Now() + database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) + } + } + database.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid) + return returnExpiry +} + +func (server *SignServer) getLastCID(uid uint32) uint32 { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var lastPlayed uint32 + _ = database.QueryRow("SELECT last_character FROM users WHERE id=$1", uid).Scan(&lastPlayed) + return lastPlayed +} + +func (server *SignServer) getUserRights(uid uint32) uint32 { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var rights uint32 + if uid != 0 { + _ = database.QueryRow("SELECT rights FROM users WHERE id=$1", uid).Scan(&rights) + _, rights = mhfcourse.GetCourseStruct(rights) + } + return rights +} + +type members struct { + CID uint32 // Local character ID + ID uint32 `db:"id"` + Name string `db:"name"` +} + +func (server *SignServer) getFriendsForCharacters(chars []character) []members { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + friends := make([]members, 0) + for _, char := range chars { + friendsCSV := "" + err := database.QueryRow("SELECT friends FROM characters WHERE id=$1", char.ID).Scan(&friendsCSV) + friendsSlice := strings.Split(friendsCSV, ",") + friendQuery := "SELECT id, name FROM characters WHERE id=" + for i := 0; i < len(friendsSlice); i++ { + friendQuery += friendsSlice[i] + if i+1 != len(friendsSlice) { + friendQuery += " OR id=" + } + } + charFriends := make([]members, 0) + err = database.Select(&charFriends, friendQuery) + if err != nil { + continue + } + for i := range charFriends { + charFriends[i].CID = char.ID + } + friends = append(friends, charFriends...) + } + return friends +} + +func (server *SignServer) getGuildmatesForCharacters(chars []character) []members { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + guildmates := make([]members, 0) + for _, char := range chars { + var inGuild int + _ = database.QueryRow("SELECT count(*) FROM guild_characters WHERE character_id=$1", char.ID).Scan(&inGuild) + if inGuild > 0 { + var guildID int + err := database.QueryRow("SELECT guild_id FROM guild_characters WHERE character_id=$1", char.ID).Scan(&guildID) + if err != nil { + continue + } + charGuildmates := make([]members, 0) + err = database.Select(&charGuildmates, "SELECT character_id AS id, c.name FROM guild_characters gc JOIN characters c ON c.id = gc.character_id WHERE guild_id=$1 AND character_id!=$2", guildID, char.ID) + if err != nil { + continue + } + for i := range charGuildmates { + charGuildmates[i].CID = char.ID + } + guildmates = append(guildmates, charGuildmates...) + } + } + return guildmates +} + +func (server *SignServer) deleteCharacter(cid int, token string, tokenID uint32) error { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + if !server.validateToken(token, tokenID) { + return errors.New("invalid token") + } + var isNew bool + err = database.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", cid).Scan(&isNew) + if isNew { + _, err = database.Exec("DELETE FROM characters WHERE id = $1", cid) + } else { + _, err = database.Exec("UPDATE characters SET deleted = true WHERE id = $1", cid) + } + if err != nil { + return err + } + return nil +} + +// Unused +func (server *SignServer) checkToken(uid uint32) (bool, error) { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var exists int + err = database.QueryRow("SELECT count(*) FROM sign_sessions WHERE user_id = $1", uid).Scan(&exists) + if err != nil { + return false, err + } + if exists > 0 { + return true, nil + } + return false, nil +} + +func (server *SignServer) registerUidToken(uid uint32) (uint32, string, error) { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _token := token.Generate(16) + var tid uint32 + err = database.QueryRow(`INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id`, uid, _token).Scan(&tid) + return tid, _token, err +} + +func (server *SignServer) registerPsnToken(psn string) (uint32, string, error) { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + _token := token.Generate(16) + var tid uint32 + err = database.QueryRow(`INSERT INTO sign_sessions (psn_id, token) VALUES ($1, $2) RETURNING id`, psn, _token).Scan(&tid) + return tid, _token, err +} + +func (server *SignServer) validateToken(token string, tokenID uint32) bool { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + query := `SELECT count(*) FROM sign_sessions WHERE token = $1` + if tokenID > 0 { + query += ` AND id = $2` + } + var exists int + err = database.QueryRow(query, token, tokenID).Scan(&exists) + if err != nil || exists == 0 { + return false + } + return true +} + +func (server *SignServer) validateLogin(user string, pass string) (uint32, RespID) { + database, err := db.GetDB() // Capture both return values + if err != nil { + server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + var uid uint32 + var passDB string + err = database.QueryRow(`SELECT id, password FROM users WHERE username = $1`, user).Scan(&uid, &passDB) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + server.logger.Info("User not found", zap.String("User", user)) + if config.GetConfig().AutoCreateAccount { + uid, err = server.registerDBAccount(user, pass) + if err == nil { + return uid, SIGN_SUCCESS + } else { + return 0, SIGN_EABORT + } + } + return 0, SIGN_EAUTH + } + return 0, SIGN_EABORT + } else { + if bcrypt.CompareHashAndPassword([]byte(passDB), []byte(pass)) == nil { + var bans int + err = database.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires IS NULL`, uid).Scan(&bans) + if err == nil && bans > 0 { + return uid, SIGN_EELIMINATE + } + err = database.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires > now()`, uid).Scan(&bans) + if err == nil && bans > 0 { + return uid, SIGN_ESUSPEND + } + return uid, SIGN_SUCCESS + } + return 0, SIGN_EPASS + } +} diff --git a/server/signserver/dsgn_resp.go b/server/sign/dsgn_resp.go similarity index 86% rename from server/signserver/dsgn_resp.go rename to server/sign/dsgn_resp.go index 486e3b9e1..cd6b24741 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/sign/dsgn_resp.go @@ -1,12 +1,13 @@ -package signserver +package sign import ( "erupe-ce/utils/byteframe" + "erupe-ce/utils/db" "erupe-ce/utils/gametime" ps "erupe-ce/utils/pascalstring" "erupe-ce/utils/stringsupport" - _config "erupe-ce/config" + "erupe-ce/config" "fmt" "strings" "time" @@ -40,7 +41,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte { return bf.Data() } - if s.client == PS3 && (s.server.erupeConfig.PatchServerFile == "" || s.server.erupeConfig.PatchServerManifest == "") { + if s.client == PS3 && (config.GetConfig().PatchServerFile == "" || config.GetConfig().PatchServerManifest == "") { bf.WriteUint8(uint8(SIGN_EABORT)) return bf.Data() } @@ -53,16 +54,16 @@ func (s *Session) makeSignResponse(uid uint32) []byte { bf.WriteBytes([]byte(sessToken)) bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) if s.client == PS3 { - ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerManifest), false) - ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerFile), false) + ps.Uint8(bf, fmt.Sprintf("%s/ps3", config.GetConfig().PatchServerManifest), false) + ps.Uint8(bf, fmt.Sprintf("%s/ps3", config.GetConfig().PatchServerFile), false) } else { - ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false) - ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false) + ps.Uint8(bf, config.GetConfig().PatchServerManifest, false) + ps.Uint8(bf, config.GetConfig().PatchServerFile, false) } if strings.Split(s.rawConn.RemoteAddr().String(), ":")[0] == "127.0.0.1" { - ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", s.server.erupeConfig.Entrance.Port), false) + ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", config.GetConfig().Entrance.Port), false) } else { - ps.Uint8(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.Host, s.server.erupeConfig.Entrance.Port), false) + ps.Uint8(bf, fmt.Sprintf("%s:%d", config.GetConfig().Host, config.GetConfig().Entrance.Port), false) } lastPlayed := uint32(0) @@ -71,7 +72,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte { lastPlayed = char.ID } bf.WriteUint32(char.ID) - if s.server.erupeConfig.DebugOptions.MaxLauncherHR { + if config.GetConfig().DebugOptions.MaxLauncherHR { bf.WriteUint16(999) } else { bf.WriteUint16(char.HR) @@ -84,7 +85,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte { bf.WriteBool(true) // Use uint16 GR, no reason not to bf.WriteBytes(stringsupport.PaddedString(char.Name, 16, true)) // Character name bf.WriteBytes(stringsupport.PaddedString(char.UnkDescString, 32, false)) // unk str - if s.server.erupeConfig.ClientID >= _config.G7 { + if config.GetConfig().ClientID >= config.G7 { bf.WriteUint16(char.GR) bf.WriteUint8(0) // Unk bf.WriteUint8(0) // Unk @@ -125,13 +126,13 @@ func (s *Session) makeSignResponse(uid uint32) []byte { } } - if s.server.erupeConfig.HideLoginNotice { + if config.GetConfig().HideLoginNotice { bf.WriteBool(false) } else { bf.WriteBool(true) bf.WriteUint8(0) bf.WriteUint8(0) - ps.Uint16(bf, strings.Join(s.server.erupeConfig.LoginNotices[:], ""), true) + ps.Uint16(bf, strings.Join(config.GetConfig().LoginNotices[:], ""), true) } bf.WriteUint32(s.server.getLastCID(uid)) @@ -332,18 +333,21 @@ func (s *Session) makeSignResponse(uid uint32) []byte { bf.WriteUint16(uint16(len(filters.Data()))) bf.WriteBytes(filters.Data()) - + database, err := db.GetDB() // Capture both return values + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if s.client == VITA || s.client == PS3 || s.client == PS4 { var psnUser string - s.server.db.QueryRow("SELECT psn_id FROM users WHERE id = $1", uid).Scan(&psnUser) + database.QueryRow("SELECT psn_id FROM users WHERE id = $1", uid).Scan(&psnUser) bf.WriteBytes(stringsupport.PaddedString(psnUser, 20, true)) } - bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[0]) - if s.server.erupeConfig.DebugOptions.CapLink.Values[0] == 51728 { - bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[1]) - if s.server.erupeConfig.DebugOptions.CapLink.Values[1] == 20000 || s.server.erupeConfig.DebugOptions.CapLink.Values[1] == 20002 { - ps.Uint16(bf, s.server.erupeConfig.DebugOptions.CapLink.Key, false) + bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[0]) + if config.GetConfig().DebugOptions.CapLink.Values[0] == 51728 { + bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[1]) + if config.GetConfig().DebugOptions.CapLink.Values[1] == 20000 || config.GetConfig().DebugOptions.CapLink.Values[1] == 20002 { + ps.Uint16(bf, config.GetConfig().DebugOptions.CapLink.Key, false) } } caStruct := []struct { @@ -357,31 +361,31 @@ func (s *Session) makeSignResponse(uid uint32) []byte { bf.WriteUint32(caStruct[i].Unk1) ps.Uint8(bf, caStruct[i].Unk2, false) } - bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[2]) - bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[3]) - bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[4]) - if s.server.erupeConfig.DebugOptions.CapLink.Values[2] == 51729 && s.server.erupeConfig.DebugOptions.CapLink.Values[3] == 1 && s.server.erupeConfig.DebugOptions.CapLink.Values[4] == 20000 { - ps.Uint16(bf, fmt.Sprintf(`%s:%d`, s.server.erupeConfig.DebugOptions.CapLink.Host, s.server.erupeConfig.DebugOptions.CapLink.Port), false) + bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[2]) + bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[3]) + bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[4]) + if config.GetConfig().DebugOptions.CapLink.Values[2] == 51729 && config.GetConfig().DebugOptions.CapLink.Values[3] == 1 && config.GetConfig().DebugOptions.CapLink.Values[4] == 20000 { + ps.Uint16(bf, fmt.Sprintf(`%s:%d`, config.GetConfig().DebugOptions.CapLink.Host, config.GetConfig().DebugOptions.CapLink.Port), false) } bf.WriteUint32(uint32(s.server.getReturnExpiry(uid).Unix())) bf.WriteUint32(0) tickets := []uint32{ - s.server.erupeConfig.GameplayOptions.MezFesSoloTickets, - s.server.erupeConfig.GameplayOptions.MezFesGroupTickets, + config.GetConfig().GameplayOptions.MezFesSoloTickets, + config.GetConfig().GameplayOptions.MezFesGroupTickets, } stalls := []uint8{ 10, 3, 6, 9, 4, 8, 5, 7, } - if s.server.erupeConfig.GameplayOptions.MezFesSwitchMinigame { + if config.GetConfig().GameplayOptions.MezFesSwitchMinigame { stalls[4] = 2 } // We can just use the start timestamp as the event ID bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix())) // Start time - bf.WriteUint32(uint32(gametime.TimeWeekNext().Add(-time.Duration(s.server.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix())) + bf.WriteUint32(uint32(gametime.TimeWeekNext().Add(-time.Duration(config.GetConfig().GameplayOptions.MezFesDuration) * time.Second).Unix())) // End time bf.WriteUint32(uint32(gametime.TimeWeekNext().Unix())) bf.WriteUint8(uint8(len(tickets))) diff --git a/server/signserver/respid.go b/server/sign/respid.go similarity index 98% rename from server/signserver/respid.go rename to server/sign/respid.go index 014daa862..88f988a4f 100644 --- a/server/signserver/respid.go +++ b/server/sign/respid.go @@ -1,4 +1,4 @@ -package signserver +package sign type RespID uint8 diff --git a/server/signserver/session.go b/server/sign/session.go similarity index 78% rename from server/signserver/session.go rename to server/sign/session.go index fa3b0f99c..2b437e9dd 100644 --- a/server/signserver/session.go +++ b/server/sign/session.go @@ -1,9 +1,12 @@ -package signserver +package sign import ( "database/sql" "encoding/hex" + "erupe-ce/config" + "erupe-ce/utils/db" "erupe-ce/utils/logger" + "erupe-ce/utils/stringsupport" "fmt" "net" @@ -30,7 +33,7 @@ const ( type Session struct { sync.Mutex logger logger.Logger - server *Server + server *SignServer rawConn net.Conn cryptConn *network.CryptConn client client @@ -40,7 +43,7 @@ type Session struct { func (s *Session) work() { pkt, err := s.cryptConn.ReadPacket() - if s.server.erupeConfig.DebugOptions.LogInboundMessages { + if config.GetConfig().DebugOptions.LogInboundMessages { fmt.Printf("\n[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt)) } @@ -84,7 +87,7 @@ func (s *Session) handlePacket(pkt []byte) error { } default: s.logger.Warn("Unknown request", zap.String("reqType", reqType)) - if s.server.erupeConfig.DebugOptions.LogInboundMessages { + if config.GetConfig().DebugOptions.LogInboundMessages { fmt.Printf("\n[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt)) } } @@ -108,7 +111,7 @@ func (s *Session) authenticate(username string, password string) { default: bf.WriteUint8(uint8(resp)) } - if s.server.erupeConfig.DebugOptions.LogOutboundMessages { + if config.GetConfig().DebugOptions.LogOutboundMessages { fmt.Printf("\n[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(bf.Data()), hex.Dump(bf.Data())) } _ = s.cryptConn.SendPacket(bf.Data()) @@ -118,7 +121,11 @@ func (s *Session) handleWIIUSGN(bf *byteframe.ByteFrame) { _ = bf.ReadBytes(1) wiiuKey := string(bf.ReadBytes(64)) var uid uint32 - err := s.server.db.QueryRow(`SELECT id FROM users WHERE wiiu_key = $1`, wiiuKey).Scan(&uid) + database, err := db.GetDB() // Capture both return values + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow(`SELECT id FROM users WHERE wiiu_key = $1`, wiiuKey).Scan(&uid) if err != nil { if err == sql.ErrNoRows { s.logger.Info("Unlinked Wii U attempted to authenticate", zap.String("Key", wiiuKey)) @@ -145,7 +152,11 @@ func (s *Session) handlePSSGN(bf *byteframe.ByteFrame) { } s.psn = string(bf.ReadNullTerminatedBytes()) var uid uint32 - err := s.server.db.QueryRow(`SELECT id FROM users WHERE psn_id = $1`, s.psn).Scan(&uid) + database, err := db.GetDB() // Capture both return values + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } + err = database.QueryRow(`SELECT id FROM users WHERE psn_id = $1`, s.psn).Scan(&uid) if err != nil { if err == sql.ErrNoRows { s.cryptConn.SendPacket(s.makeSignResponse(0)) @@ -162,9 +173,13 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) { credentials := strings.Split(stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()), "\n") token := string(bf.ReadNullTerminatedBytes()) uid, resp := s.server.validateLogin(credentials[0], credentials[1]) + database, err := db.GetDB() // Capture both return values + if err != nil { + s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err)) + } if resp == SIGN_SUCCESS && uid > 0 { var psn string - err := s.server.db.QueryRow(`SELECT psn_id FROM sign_sessions WHERE token = $1`, token).Scan(&psn) + err := database.QueryRow(`SELECT psn_id FROM sign_sessions WHERE token = $1`, token).Scan(&psn) if err != nil { s.sendCode(SIGN_ECOGLINK) return @@ -172,7 +187,7 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) { // Since we check for the psn_id, this will never run var exists int - err = s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, psn).Scan(&exists) + err = database.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, psn).Scan(&exists) if err != nil { s.sendCode(SIGN_ECOGLINK) return @@ -182,7 +197,7 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) { } var currentPSN string - err = s.server.db.QueryRow(`SELECT COALESCE(psn_id, '') FROM users WHERE username = $1`, credentials[0]).Scan(¤tPSN) + err = database.QueryRow(`SELECT COALESCE(psn_id, '') FROM users WHERE username = $1`, credentials[0]).Scan(¤tPSN) if err != nil { s.sendCode(SIGN_ECOGLINK) return @@ -191,7 +206,7 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) { return } - _, err = s.server.db.Exec(`UPDATE users SET psn_id = $1 WHERE username = $2`, psn, credentials[0]) + _, err = database.Exec(`UPDATE users SET psn_id = $1 WHERE username = $2`, psn, credentials[0]) if err == nil { s.sendCode(SIGN_SUCCESS) return diff --git a/server/signserver/sign_server.go b/server/sign/sign_server.go similarity index 68% rename from server/signserver/sign_server.go rename to server/sign/sign_server.go index 0aaac5d80..a7e835bd3 100644 --- a/server/signserver/sign_server.go +++ b/server/sign/sign_server.go @@ -1,4 +1,4 @@ -package signserver +package sign import ( "fmt" @@ -6,44 +6,33 @@ import ( "net" "sync" - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/network" "erupe-ce/utils/logger" - "github.com/jmoiron/sqlx" "go.uber.org/zap" ) -// Config struct allows configuring the server. -type Config struct { - DB *sqlx.DB - ErupeConfig *_config.Config -} - -// Server is a MHF sign server. -type Server struct { +// SignServer is a MHF sign server. +type SignServer struct { sync.Mutex logger logger.Logger - erupeConfig *_config.Config sessions map[int]*Session - db *sqlx.DB listener net.Listener isShuttingDown bool } // NewServer creates a new Server type. -func NewServer(config *Config) *Server { - s := &Server{ - logger: logger.Get().Named("sign"), - erupeConfig: config.ErupeConfig, - db: config.DB, +func NewServer() *SignServer { + s := &SignServer{ + logger: logger.Get().Named("sign"), } return s } // Start starts the server in a new goroutine. -func (server *Server) Start() error { - l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.erupeConfig.Sign.Port)) +func (server *SignServer) Start() error { + l, err := net.Listen("tcp", fmt.Sprintf(":%d", config.GetConfig().Sign.Port)) if err != nil { return err } @@ -55,7 +44,7 @@ func (server *Server) Start() error { } // Shutdown exits the server gracefully. -func (server *Server) Shutdown() { +func (server *SignServer) Shutdown() { server.logger.Debug("Shutting down...") server.Lock() @@ -66,7 +55,7 @@ func (server *Server) Shutdown() { server.listener.Close() } -func (server *Server) acceptClients() { +func (server *SignServer) acceptClients() { for { conn, err := server.listener.Accept() if err != nil { @@ -86,7 +75,7 @@ func (server *Server) acceptClients() { } } -func (server *Server) handleConnection(conn net.Conn) { +func (server *SignServer) handleConnection(conn net.Conn) { server.logger.Debug("New connection", zap.String("RemoteAddr", conn.RemoteAddr().String())) defer conn.Close() diff --git a/server/signserver/dbutils.go b/server/signserver/dbutils.go deleted file mode 100644 index efe49267e..000000000 --- a/server/signserver/dbutils.go +++ /dev/null @@ -1,260 +0,0 @@ -package signserver - -import ( - "database/sql" - "errors" - "erupe-ce/utils/mhfcourse" - "erupe-ce/utils/token" - "strings" - "time" - - "go.uber.org/zap" - "golang.org/x/crypto/bcrypt" -) - -func (server *Server) newUserChara(uid uint32) error { - var numNewChars int - err := server.db.QueryRow("SELECT COUNT(*) FROM characters WHERE user_id = $1 AND is_new_character = true", uid).Scan(&numNewChars) - if err != nil { - return err - } - - // prevent users with an uninitialised character from creating more - if numNewChars >= 1 { - return err - } - - _, err = server.db.Exec(` - INSERT INTO characters ( - user_id, is_female, is_new_character, name, unk_desc_string, - hr, gr, weapon_type, last_login) - VALUES($1, False, True, '', '', 0, 0, 0, $2)`, - uid, - uint32(time.Now().Unix()), - ) - if err != nil { - return err - } - - return nil -} - -func (server *Server) registerDBAccount(username string, password string) (uint32, error) { - var uid uint32 - server.logger.Info("Creating user", zap.String("User", username)) - - // Create salted hash of user password - passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - if err != nil { - return 0, err - } - - err = server.db.QueryRow("INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3) RETURNING id", username, string(passwordHash), time.Now().Add(time.Hour*24*30)).Scan(&uid) - if err != nil { - return 0, err - } - - return uid, nil -} - -type character struct { - ID uint32 `db:"id"` - IsFemale bool `db:"is_female"` - IsNewCharacter bool `db:"is_new_character"` - Name string `db:"name"` - UnkDescString string `db:"unk_desc_string"` - HR uint16 `db:"hr"` - GR uint16 `db:"gr"` - WeaponType uint16 `db:"weapon_type"` - LastLogin uint32 `db:"last_login"` -} - -func (server *Server) getCharactersForUser(uid uint32) ([]character, error) { - characters := make([]character, 0) - err := server.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hr, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY id", uid) - if err != nil { - return nil, err - } - return characters, nil -} - -func (server *Server) getReturnExpiry(uid uint32) time.Time { - var returnExpiry, lastLogin time.Time - server.db.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid) - if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) { - returnExpiry = time.Now().Add(time.Hour * 24 * 30) - server.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) - } else { - err := server.db.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid) - if err != nil { - returnExpiry = time.Now() - server.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid) - } - } - server.db.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid) - return returnExpiry -} - -func (server *Server) getLastCID(uid uint32) uint32 { - var lastPlayed uint32 - _ = server.db.QueryRow("SELECT last_character FROM users WHERE id=$1", uid).Scan(&lastPlayed) - return lastPlayed -} - -func (server *Server) getUserRights(uid uint32) uint32 { - var rights uint32 - if uid != 0 { - _ = server.db.QueryRow("SELECT rights FROM users WHERE id=$1", uid).Scan(&rights) - _, rights = mhfcourse.GetCourseStruct(rights) - } - return rights -} - -type members struct { - CID uint32 // Local character ID - ID uint32 `db:"id"` - Name string `db:"name"` -} - -func (server *Server) getFriendsForCharacters(chars []character) []members { - friends := make([]members, 0) - for _, char := range chars { - friendsCSV := "" - err := server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", char.ID).Scan(&friendsCSV) - friendsSlice := strings.Split(friendsCSV, ",") - friendQuery := "SELECT id, name FROM characters WHERE id=" - for i := 0; i < len(friendsSlice); i++ { - friendQuery += friendsSlice[i] - if i+1 != len(friendsSlice) { - friendQuery += " OR id=" - } - } - charFriends := make([]members, 0) - err = server.db.Select(&charFriends, friendQuery) - if err != nil { - continue - } - for i := range charFriends { - charFriends[i].CID = char.ID - } - friends = append(friends, charFriends...) - } - return friends -} - -func (server *Server) getGuildmatesForCharacters(chars []character) []members { - guildmates := make([]members, 0) - for _, char := range chars { - var inGuild int - _ = server.db.QueryRow("SELECT count(*) FROM guild_characters WHERE character_id=$1", char.ID).Scan(&inGuild) - if inGuild > 0 { - var guildID int - err := server.db.QueryRow("SELECT guild_id FROM guild_characters WHERE character_id=$1", char.ID).Scan(&guildID) - if err != nil { - continue - } - charGuildmates := make([]members, 0) - err = server.db.Select(&charGuildmates, "SELECT character_id AS id, c.name FROM guild_characters gc JOIN characters c ON c.id = gc.character_id WHERE guild_id=$1 AND character_id!=$2", guildID, char.ID) - if err != nil { - continue - } - for i := range charGuildmates { - charGuildmates[i].CID = char.ID - } - guildmates = append(guildmates, charGuildmates...) - } - } - return guildmates -} - -func (server *Server) deleteCharacter(cid int, token string, tokenID uint32) error { - if !server.validateToken(token, tokenID) { - return errors.New("invalid token") - } - var isNew bool - err := server.db.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", cid).Scan(&isNew) - if isNew { - _, err = server.db.Exec("DELETE FROM characters WHERE id = $1", cid) - } else { - _, err = server.db.Exec("UPDATE characters SET deleted = true WHERE id = $1", cid) - } - if err != nil { - return err - } - return nil -} - -// Unused -func (server *Server) checkToken(uid uint32) (bool, error) { - var exists int - err := server.db.QueryRow("SELECT count(*) FROM sign_sessions WHERE user_id = $1", uid).Scan(&exists) - if err != nil { - return false, err - } - if exists > 0 { - return true, nil - } - return false, nil -} - -func (server *Server) registerUidToken(uid uint32) (uint32, string, error) { - _token := token.Generate(16) - var tid uint32 - err := server.db.QueryRow(`INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id`, uid, _token).Scan(&tid) - return tid, _token, err -} - -func (server *Server) registerPsnToken(psn string) (uint32, string, error) { - _token := token.Generate(16) - var tid uint32 - err := server.db.QueryRow(`INSERT INTO sign_sessions (psn_id, token) VALUES ($1, $2) RETURNING id`, psn, _token).Scan(&tid) - return tid, _token, err -} - -func (server *Server) validateToken(token string, tokenID uint32) bool { - query := `SELECT count(*) FROM sign_sessions WHERE token = $1` - if tokenID > 0 { - query += ` AND id = $2` - } - var exists int - err := server.db.QueryRow(query, token, tokenID).Scan(&exists) - if err != nil || exists == 0 { - return false - } - return true -} - -func (server *Server) validateLogin(user string, pass string) (uint32, RespID) { - var uid uint32 - var passDB string - err := server.db.QueryRow(`SELECT id, password FROM users WHERE username = $1`, user).Scan(&uid, &passDB) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - server.logger.Info("User not found", zap.String("User", user)) - if server.erupeConfig.AutoCreateAccount { - uid, err = server.registerDBAccount(user, pass) - if err == nil { - return uid, SIGN_SUCCESS - } else { - return 0, SIGN_EABORT - } - } - return 0, SIGN_EAUTH - } - return 0, SIGN_EABORT - } else { - if bcrypt.CompareHashAndPassword([]byte(passDB), []byte(pass)) == nil { - var bans int - err = server.db.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires IS NULL`, uid).Scan(&bans) - if err == nil && bans > 0 { - return uid, SIGN_EELIMINATE - } - err = server.db.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires > now()`, uid).Scan(&bans) - if err == nil && bans > 0 { - return uid, SIGN_ESUSPEND - } - return uid, SIGN_SUCCESS - } - return 0, SIGN_EPASS - } -} diff --git a/utils/db/db.go b/utils/db/db.go new file mode 100644 index 000000000..7ccc9d6a0 --- /dev/null +++ b/utils/db/db.go @@ -0,0 +1,77 @@ +package db + +import ( + "fmt" + "sync" + + "erupe-ce/config" + "erupe-ce/utils/logger" + + "github.com/jmoiron/sqlx" + _ "github.com/lib/pq" // Postgres driver +) + +var ( + instance *sqlx.DB + once sync.Once + dbLogger logger.Logger +) + +// InitDB initializes the database connection pool as a singleton +func InitDB(config *config.Config) (*sqlx.DB, error) { + dbLogger = logger.Get().Named("database") + var err error + once.Do(func() { + // Create the postgres DB pool. + connectString := fmt.Sprintf( + "host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable", + config.Database.Host, + config.Database.Port, + config.Database.User, + config.Database.Password, + config.Database.Database, + ) + + instance, err = sqlx.Open("postgres", connectString) + if err != nil { + return // Stop here if there's an error opening the database + } + + // Test the DB connection. + err = instance.Ping() + if err != nil { + return // Stop here if there's an error pinging the database + } + dbLogger.Info("Database: Started successfully") + + // Clear stale data + if config.DebugOptions.ProxyPort == 0 { + _ = instance.MustExec("DELETE FROM sign_sessions") + } + _ = instance.MustExec("DELETE FROM servers") + _ = instance.MustExec(`UPDATE guild_characters SET treasure_hunt=NULL`) + + // Clean the DB if the option is on. + if config.DebugOptions.CleanDB { + dbLogger.Info("Database: Started clearing...") + cleanDB(instance) + dbLogger.Info("Database: Finished clearing") + } + }) + return instance, err +} + +func GetDB() (*sqlx.DB, error) { + if instance == nil { + return nil, fmt.Errorf("database not initialized") + } + return instance, nil +} + +// Temporary DB auto clean on startup for quick development & testing. +func cleanDB(db *sqlx.DB) { + _ = db.MustExec("DELETE FROM guild_characters") + _ = db.MustExec("DELETE FROM guilds") + _ = db.MustExec("DELETE FROM characters") + _ = db.MustExec("DELETE FROM users") +} diff --git a/utils/mhfcourse/mhfcourse.go b/utils/mhfcourse/mhfcourse.go index 71ccc0ab7..442a37bf3 100644 --- a/utils/mhfcourse/mhfcourse.go +++ b/utils/mhfcourse/mhfcourse.go @@ -1,7 +1,7 @@ package mhfcourse import ( - _config "erupe-ce/config" + "erupe-ce/config" "math" "sort" "time" @@ -68,7 +68,7 @@ func CourseExists(ID uint16, c []Course) bool { // GetCourseStruct returns a slice of Course(s) from a rights integer func GetCourseStruct(rights uint32) ([]Course, uint32) { var resp []Course - for _, c := range _config.ErupeConfig.DefaultCourses { + for _, c := range config.GetConfig().DefaultCourses { resp = append(resp, Course{ID: c}) } s := Courses() diff --git a/utils/mhfitem/mhfitem.go b/utils/mhfitem/mhfitem.go index 343fa7084..05c82ac4c 100644 --- a/utils/mhfitem/mhfitem.go +++ b/utils/mhfitem/mhfitem.go @@ -1,7 +1,7 @@ package mhfitem import ( - _config "erupe-ce/config" + "erupe-ce/config" "erupe-ce/utils/byteframe" "erupe-ce/utils/token" ) @@ -114,7 +114,7 @@ func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment { for i := 0; i < 3; i++ { equipment.Decorations[i].ItemID = bf.ReadUint16() } - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { equipment.Sigils[i].Effects[j].ID = bf.ReadUint16() @@ -128,7 +128,7 @@ func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment { equipment.Sigils[i].Unk3 = bf.ReadUint8() } } - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { equipment.Unk1 = bf.ReadUint16() } return equipment @@ -144,7 +144,7 @@ func (e MHFEquipment) ToBytes() []byte { for i := 0; i < 3; i++ { bf.WriteUint16(e.Decorations[i].ItemID) } - if _config.ErupeConfig.ClientID >= _config.G1 { + if config.GetConfig().ClientID >= config.G1 { for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { bf.WriteUint16(e.Sigils[i].Effects[j].ID) @@ -158,7 +158,7 @@ func (e MHFEquipment) ToBytes() []byte { bf.WriteUint8(e.Sigils[i].Unk3) } } - if _config.ErupeConfig.ClientID >= _config.Z1 { + if config.GetConfig().ClientID >= config.Z1 { bf.WriteUint16(e.Unk1) } return bf.Data()