From e39630564e1d62381393cc89a1861ba604803dd3 Mon Sep 17 00:00:00 2001 From: rockisch Date: Wed, 22 Nov 2023 00:01:04 -0300 Subject: [PATCH 1/7] Add dev proxy config --- config.json | 1 + config/config.go | 29 +++++++++++++++-------------- main.go | 12 ++++++++---- server/entranceserver/make_resp.go | 6 +++++- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/config.json b/config.json index e3e2b7ea4..bfa9e04de 100644 --- a/config.json +++ b/config.json @@ -29,6 +29,7 @@ "MezFesAlt": false, "DisableTokenCheck": false, "QuestDebugTools": false, + "ProxyPort": 0, "EarthStatusOverride": 0, "EarthIDOverride": 0, "EarthMonsterOverride": 0, diff --git a/config/config.go b/config/config.go index ee0e6b377..c9a05d3d1 100644 --- a/config/config.go +++ b/config/config.go @@ -96,20 +96,21 @@ type Config struct { // DevModeOptions holds various debug/temporary options for use while developing Erupe. type DevModeOptions struct { - AutoCreateAccount bool // Automatically create accounts if they don't exist - CleanDB bool // Automatically wipes the DB on server reset. - MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. - LogInboundMessages bool // Log all messages sent to the server - LogOutboundMessages bool // Log all messages sent to the clients - LogMessageData bool // Log all bytes transferred as a hexdump - MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled - DivaEvent int // Diva Defense event status - FestaEvent int // Hunter's Festa event status - TournamentEvent int // VS Tournament event status - MezFesEvent bool // MezFes status - MezFesAlt bool // Swaps out Volpakkun for Tokotoko - DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) - QuestDebugTools bool // Enable various quest debug logs + AutoCreateAccount bool // Automatically create accounts if they don't exist + CleanDB bool // Automatically wipes the DB on server reset. + MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. + LogInboundMessages bool // Log all messages sent to the server + LogOutboundMessages bool // Log all messages sent to the clients + LogMessageData bool // Log all bytes transferred as a hexdump + MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled + DivaEvent int // Diva Defense event status + FestaEvent int // Hunter's Festa event status + TournamentEvent int // VS Tournament event status + MezFesEvent bool // MezFes status + MezFesAlt bool // Swaps out Volpakkun for Tokotoko + DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) + QuestDebugTools bool // Enable various quest debug logs + ProxyPort uint16 // Forces the game connect to a channel server proxy EarthStatusOverride int32 EarthIDOverride int32 EarthMonsterOverride int32 diff --git a/main.go b/main.go index 2a538b094..724fe3f44 100644 --- a/main.go +++ b/main.go @@ -22,11 +22,13 @@ import ( ) // Temporary DB auto clean on startup for quick development & testing. -func cleanDB(db *sqlx.DB) { +func cleanDB(db *sqlx.DB, config *_config.Config) { _ = db.MustExec("DELETE FROM guild_characters") _ = db.MustExec("DELETE FROM guilds") _ = db.MustExec("DELETE FROM characters") - _ = db.MustExec("DELETE FROM sign_sessions") + if !config.DevMode || config.DevModeOptions.ProxyPort == 0 { + _ = db.MustExec("DELETE FROM sign_sessions") + } _ = db.MustExec("DELETE FROM users") } @@ -124,14 +126,16 @@ func main() { logger.Info("Database: Started successfully") // Clear stale data - _ = db.MustExec("DELETE FROM sign_sessions") + if !config.DevMode || config.DevModeOptions.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.DevMode && config.DevModeOptions.CleanDB { logger.Info("Database: Started clearing...") - cleanDB(db) + cleanDB(db, config) logger.Info("Database: Finished clearing") } diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index eaa023c5b..5ace5a427 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -69,7 +69,11 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { for channelIdx, ci := range si.Channels { sid = (4096 + serverIdx*256) + (16 + channelIdx) - bf.WriteUint16(ci.Port) + if _config.ErupeConfig.DevMode && _config.ErupeConfig.DevModeOptions.ProxyPort != 0 { + bf.WriteUint16(_config.ErupeConfig.DevModeOptions.ProxyPort) + } else { + bf.WriteUint16(ci.Port) + } bf.WriteUint16(16 + uint16(channelIdx)) bf.WriteUint16(ci.MaxPlayers) var currentPlayers uint16 From b3af01b8037e0c014f503b25fdb66850b3767293 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 18:54:04 +1100 Subject: [PATCH 2/7] use seconds for arbitrary durations in config --- config.json | 4 ++-- config/config.go | 4 ++-- server/channelserver/handlers_cafe.go | 2 +- server/channelserver/handlers_guild.go | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config.json b/config.json index 9fcb4ef68..2a9b06e6f 100644 --- a/config.json +++ b/config.json @@ -45,8 +45,8 @@ "TreasureHuntExpiry": 604800, "DisableLoginBoost": false, "DisableBoostTime": false, - "BoostTimeDuration": 120, - "GuildMealDuration": 60, + "BoostTimeDuration": 7200, + "GuildMealDuration": 3600, "BonusQuestAllowance": 3, "DailyQuestAllowance": 1, "MezfesSoloTickets": 10, diff --git a/config/config.go b/config/config.go index e992d6594..09991c84f 100644 --- a/config/config.go +++ b/config/config.go @@ -131,8 +131,8 @@ type GameplayOptions struct { TreasureHuntPartnyaCooldown uint32 // Seconds until a Partnya can be assigned to another Clan Treasure Hunt DisableLoginBoost bool // Disables the Login Boost system DisableBoostTime bool // Disables the daily NetCafe Boost Time - BoostTimeDuration int // The number of minutes NetCafe Boost Time lasts for - GuildMealDuration int // The number of minutes a Guild Meal can be activated for after cooking + BoostTimeDuration int // Second that the NetCafe Boost Time lasts + GuildMealDuration int // Second that a Guild Meal can be activated for after cooking BonusQuestAllowance uint32 // Number of Bonus Point Quests to allow daily DailyQuestAllowance uint32 // Number of Daily Quests to allow daily MezfesSoloTickets uint32 // Number of solo tickets given weekly diff --git a/server/channelserver/handlers_cafe.go b/server/channelserver/handlers_cafe.go index 67b7c3807..9c4b0b732 100644 --- a/server/channelserver/handlers_cafe.go +++ b/server/channelserver/handlers_cafe.go @@ -220,7 +220,7 @@ func addPointNetcafe(s *Session, p int) error { func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfStartBoostTime) bf := byteframe.NewByteFrame() - boostLimit := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.BoostTimeDuration) * time.Minute) + boostLimit := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.BoostTimeDuration) * time.Second) if s.server.erupeConfig.GameplayOptions.DisableBoostTime { bf.WriteUint32(0) doAckBufSucceed(s, pkt.AckHandle, bf.Data()) diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 7a726832f..30a150eef 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -1831,18 +1831,18 @@ func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfRegistGuildCooking) guild, _ := GetGuildInfoByCharacterId(s, s.charID) - currentTime := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.GuildMealDuration-60) * time.Minute) + startTime := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.GuildMealDuration-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, currentTime, pkt.OverwriteID) + 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) } 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, currentTime).Scan(&pkt.OverwriteID) + 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) } bf := byteframe.NewByteFrame() bf.WriteUint16(1) bf.WriteUint32(pkt.OverwriteID) bf.WriteUint32(uint32(pkt.MealID)) bf.WriteUint32(uint32(pkt.Success)) - bf.WriteUint32(uint32(currentTime.Unix())) + bf.WriteUint32(uint32(startTime.Unix())) doAckBufSucceed(s, pkt.AckHandle, bf.Data()) } From a0fbfc248b9ea92e1b95472b41d42a322b89b47b Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 19:21:31 +1100 Subject: [PATCH 3/7] fix TimeWeekX inconsistencies & limit MezFes duration --- config.json | 1 + config/config.go | 1 + server/channelserver/handlers.go | 4 ++-- server/channelserver/sys_time.go | 7 +++++-- server/signserver/dsgn_resp.go | 3 ++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/config.json b/config.json index 2a9b06e6f..e945f8d33 100644 --- a/config.json +++ b/config.json @@ -65,6 +65,7 @@ "MaterialMultiplier": 1.00, "ExtraCarves": 0, "DisableHunterNavi": false, + "MezFesDuration": 172800, "EnableKaijiEvent": false, "EnableHiganjimaEvent": false, "EnableNierEvent": false, diff --git a/config/config.go b/config/config.go index 09991c84f..4d74accce 100644 --- a/config/config.go +++ b/config/config.go @@ -151,6 +151,7 @@ type GameplayOptions struct { MaterialMultiplier float32 // Adjusts the multiplier of Monster Materials rewarded for quest completion ExtraCarves uint16 // Grant n extra chances to carve ALL carcasses DisableHunterNavi bool // Disables the Hunter Navi + MezFesDuration int // Seconds that MezFes will last for weekly (from 12AM Mon backwards) EnableKaijiEvent bool // Enables the Kaiji event in the Rasta Bar EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 154dbc100..e0d162b03 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -988,8 +988,8 @@ func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetEarthStatus) bf := byteframe.NewByteFrame() - bf.WriteUint32(uint32(TimeWeekStart().Add(time.Hour * -24).Unix())) // Start - bf.WriteUint32(uint32(TimeWeekNext().Add(time.Hour * 24).Unix())) // End + bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start + bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride) bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthMonsterOverride) diff --git a/server/channelserver/sys_time.go b/server/channelserver/sys_time.go index a41b18b2e..bae61a1c6 100644 --- a/server/channelserver/sys_time.go +++ b/server/channelserver/sys_time.go @@ -16,8 +16,11 @@ func TimeMidnight() time.Time { func TimeWeekStart() time.Time { midnight := TimeMidnight() - offset := (int(midnight.Weekday()) - 1) * -24 - return midnight.Add(time.Hour * time.Duration(offset)) + offset := int(midnight.Weekday()) - int(time.Monday) + if offset < 0 { + offset += 7 + } + return midnight.Add(-time.Duration(offset) * 24 * time.Hour) } func TimeWeekNext() time.Time { diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 77ac6468d..450dc7fc7 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -9,6 +9,7 @@ import ( "fmt" "go.uber.org/zap" "strings" + "time" ) func (s *Session) makeSignResponse(uid uint32) []byte { @@ -160,7 +161,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte { // We can just use the start timestamp as the event ID bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) // Start time - bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) + bf.WriteUint32(uint32(channelserver.TimeWeekNext().Add(-time.Duration(s.server.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix())) // End time bf.WriteUint32(uint32(channelserver.TimeWeekNext().Unix())) bf.WriteUint8(2) // Unk From dfc359f5e211401ca59e64c88892ff299ed992c0 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 19:42:27 +1100 Subject: [PATCH 4/7] structure & change config for MezFes --- config.json | 3 +- config/config.go | 3 +- server/signserver/dsgn_resp.go | 53 +++++++++++++++------------------- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/config.json b/config.json index e945f8d33..85a84a401 100644 --- a/config.json +++ b/config.json @@ -25,8 +25,6 @@ "DivaEvent": 0, "FestaEvent": -1, "TournamentEvent": 0, - "MezFesEvent": true, - "MezFesAlt": false, "DisableTokenCheck": false, "QuestDebugTools": false, "EarthStatusOverride": 0, @@ -66,6 +64,7 @@ "ExtraCarves": 0, "DisableHunterNavi": false, "MezFesDuration": 172800, + "MezFesSwitchMinigame": false, "EnableKaijiEvent": false, "EnableHiganjimaEvent": false, "EnableNierEvent": false, diff --git a/config/config.go b/config/config.go index 4d74accce..4fdf431b1 100644 --- a/config/config.go +++ b/config/config.go @@ -106,8 +106,6 @@ type DevModeOptions struct { DivaEvent int // Diva Defense event status FestaEvent int // Hunter's Festa event status TournamentEvent int // VS Tournament event status - MezFesEvent bool // MezFes status - MezFesAlt bool // Swaps out Volpakkun for Tokotoko DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) QuestDebugTools bool // Enable various quest debug logs EarthStatusOverride int32 @@ -152,6 +150,7 @@ type GameplayOptions struct { ExtraCarves uint16 // Grant n extra chances to carve ALL carcasses DisableHunterNavi bool // Disables the Hunter Navi MezFesDuration int // Seconds that MezFes will last for weekly (from 12AM Mon backwards) + MezFesSwitchMinigame bool // Swaps out Volpakkun Together for Tokotoko Partnya EnableKaijiEvent bool // Enables the Kaiji event in the Rasta Bar EnableHiganjimaEvent bool // Enables the Higanjima event in the Rasta Bar EnableNierEvent bool // Enables the Nier event in the Rasta Bar diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 450dc7fc7..34cc371e2 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -155,35 +155,30 @@ func (s *Session) makeSignResponse(uid uint32) []byte { bf.WriteUint32(uint32(s.server.getReturnExpiry(uid).Unix())) bf.WriteUint32(0) - mezfes := s.server.erupeConfig.DevModeOptions.MezFesEvent - alt := s.server.erupeConfig.DevModeOptions.MezFesAlt - if mezfes { - // We can just use the start timestamp as the event ID - bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) - // Start time - bf.WriteUint32(uint32(channelserver.TimeWeekNext().Add(-time.Duration(s.server.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix())) - // End time - bf.WriteUint32(uint32(channelserver.TimeWeekNext().Unix())) - bf.WriteUint8(2) // Unk - bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MezfesSoloTickets) - bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MezfesGroupTickets) - bf.WriteUint8(8) // Stalls open - bf.WriteUint8(10) // Stall Map - bf.WriteUint8(3) // Pachinko - bf.WriteUint8(6) // Nyanrendo - bf.WriteUint8(9) // Point stall - if alt { - bf.WriteUint8(2) // Tokotoko Partnya - } else { - bf.WriteUint8(4) // Volpakkun Together - } - bf.WriteUint8(8) // Dokkan Battle Cats - bf.WriteUint8(5) // Goocoo Scoop - bf.WriteUint8(7) // Honey Panic - } else { - bf.WriteUint32(0) - bf.WriteUint32(0) - bf.WriteUint32(0) + tickets := []uint32{ + s.server.erupeConfig.GameplayOptions.MezfesSoloTickets, + s.server.erupeConfig.GameplayOptions.MezfesGroupTickets, + } + stalls := []uint8{ + 10, 3, 6, 9, 4, 8, 5, 7, + } + if s.server.erupeConfig.GameplayOptions.MezFesSwitchMinigame { + stalls[4] = 2 + } + + // We can just use the start timestamp as the event ID + bf.WriteUint32(uint32(channelserver.TimeWeekStart().Unix())) + // Start time + bf.WriteUint32(uint32(channelserver.TimeWeekNext().Add(-time.Duration(s.server.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix())) + // End time + bf.WriteUint32(uint32(channelserver.TimeWeekNext().Unix())) + bf.WriteUint8(uint8(len(tickets))) + for i := range tickets { + bf.WriteUint32(tickets[i]) + } + bf.WriteUint8(uint8(len(stalls))) + for i := range stalls { + bf.WriteUint8(stalls[i]) } return bf.Data() } From 662c137467c4513b2db100667fcdebb0dc7625be Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 20:44:13 +1100 Subject: [PATCH 5/7] update MezFes config for SignV2 --- server/signv2server/endpoints.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/server/signv2server/endpoints.go b/server/signv2server/endpoints.go index cde28591c..ae5959809 100644 --- a/server/signv2server/endpoints.go +++ b/server/signv2server/endpoints.go @@ -8,6 +8,7 @@ import ( "erupe-ce/server/channelserver" "net/http" "strings" + "time" "github.com/lib/pq" "go.uber.org/zap" @@ -82,19 +83,17 @@ func (s *Server) newAuthData(userID uint32, userRights uint32, userToken string, resp.Characters[i].HR = 7 } } - if s.erupeConfig.DevModeOptions.MezFesEvent { - stalls := []uint32{10, 3, 6, 9, 4, 8, 5, 7} - if s.erupeConfig.DevModeOptions.MezFesAlt { - stalls[4] = 2 - } - resp.MezFes = &MezFes{ - ID: uint32(channelserver.TimeWeekStart().Unix()), - Start: uint32(channelserver.TimeWeekStart().Unix()), - End: uint32(channelserver.TimeWeekNext().Unix()), - SoloTickets: s.erupeConfig.GameplayOptions.MezfesSoloTickets, - GroupTickets: s.erupeConfig.GameplayOptions.MezfesGroupTickets, - Stalls: stalls, - } + stalls := []uint32{10, 3, 6, 9, 4, 8, 5, 7} + if s.erupeConfig.GameplayOptions.MezFesSwitchMinigame { + stalls[4] = 2 + } + resp.MezFes = &MezFes{ + ID: uint32(channelserver.TimeWeekStart().Unix()), + Start: uint32(channelserver.TimeWeekStart().Add(-time.Duration(s.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix()), + End: uint32(channelserver.TimeWeekNext().Unix()), + SoloTickets: s.erupeConfig.GameplayOptions.MezfesSoloTickets, + GroupTickets: s.erupeConfig.GameplayOptions.MezfesGroupTickets, + Stalls: stalls, } if !s.erupeConfig.HideLoginNotice { resp.Notices = append(resp.Notices, strings.Join(s.erupeConfig.LoginNotices[:], "")) From a2f488e5e3f6805a30cd0cf5e5649630c9441f7f Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 20:50:08 +1100 Subject: [PATCH 6/7] move ProxyPort config out of DevMode --- config.json | 2 +- config/config.go | 32 +++++++++++++++--------------- main.go | 2 +- server/entranceserver/make_resp.go | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/config.json b/config.json index bfa9e04de..d6c233470 100644 --- a/config.json +++ b/config.json @@ -13,6 +13,7 @@ "DeleteOnSaveCorruption": false, "ClientMode": "ZZ", "QuestCacheExpiry": 300, + "ProxyPort": 0, "DevMode": true, "DevModeOptions": { "AutoCreateAccount": true, @@ -29,7 +30,6 @@ "MezFesAlt": false, "DisableTokenCheck": false, "QuestDebugTools": false, - "ProxyPort": 0, "EarthStatusOverride": 0, "EarthIDOverride": 0, "EarthMonsterOverride": 0, diff --git a/config/config.go b/config/config.go index c9a05d3d1..5bcea5659 100644 --- a/config/config.go +++ b/config/config.go @@ -79,7 +79,8 @@ type Config struct { DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion ClientMode string RealClientMode Mode - QuestCacheExpiry int // Number of seconds to keep quest data cached + QuestCacheExpiry int // Number of seconds to keep quest data cached + ProxyPort uint16 // Forces the game to connect to a channel server proxy DevMode bool DevModeOptions DevModeOptions @@ -96,21 +97,20 @@ type Config struct { // DevModeOptions holds various debug/temporary options for use while developing Erupe. type DevModeOptions struct { - AutoCreateAccount bool // Automatically create accounts if they don't exist - CleanDB bool // Automatically wipes the DB on server reset. - MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. - LogInboundMessages bool // Log all messages sent to the server - LogOutboundMessages bool // Log all messages sent to the clients - LogMessageData bool // Log all bytes transferred as a hexdump - MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled - DivaEvent int // Diva Defense event status - FestaEvent int // Hunter's Festa event status - TournamentEvent int // VS Tournament event status - MezFesEvent bool // MezFes status - MezFesAlt bool // Swaps out Volpakkun for Tokotoko - DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) - QuestDebugTools bool // Enable various quest debug logs - ProxyPort uint16 // Forces the game connect to a channel server proxy + AutoCreateAccount bool // Automatically create accounts if they don't exist + CleanDB bool // Automatically wipes the DB on server reset. + MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. + LogInboundMessages bool // Log all messages sent to the server + LogOutboundMessages bool // Log all messages sent to the clients + LogMessageData bool // Log all bytes transferred as a hexdump + MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled + DivaEvent int // Diva Defense event status + FestaEvent int // Hunter's Festa event status + TournamentEvent int // VS Tournament event status + MezFesEvent bool // MezFes status + MezFesAlt bool // Swaps out Volpakkun for Tokotoko + DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!) + QuestDebugTools bool // Enable various quest debug logs EarthStatusOverride int32 EarthIDOverride int32 EarthMonsterOverride int32 diff --git a/main.go b/main.go index 724fe3f44..1413392cf 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ func cleanDB(db *sqlx.DB, config *_config.Config) { _ = db.MustExec("DELETE FROM guild_characters") _ = db.MustExec("DELETE FROM guilds") _ = db.MustExec("DELETE FROM characters") - if !config.DevMode || config.DevModeOptions.ProxyPort == 0 { + if config.ProxyPort == 0 { _ = db.MustExec("DELETE FROM sign_sessions") } _ = db.MustExec("DELETE FROM users") diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 5ace5a427..4b478fa24 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -69,8 +69,8 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { for channelIdx, ci := range si.Channels { sid = (4096 + serverIdx*256) + (16 + channelIdx) - if _config.ErupeConfig.DevMode && _config.ErupeConfig.DevModeOptions.ProxyPort != 0 { - bf.WriteUint16(_config.ErupeConfig.DevModeOptions.ProxyPort) + if _config.ErupeConfig.DevMode && _config.ErupeConfig.ProxyPort != 0 { + bf.WriteUint16(_config.ErupeConfig.ProxyPort) } else { bf.WriteUint16(ci.Port) } From 3c6067c8a6da4248efc233affb838134dfce15e0 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 26 Nov 2023 23:22:56 +1100 Subject: [PATCH 7/7] port partial fix/mutex-rework --- network/mhfpacket/msg_sys_create_stage.go | 7 ++-- network/mhfpacket/msg_sys_enter_stage.go | 6 +-- network/mhfpacket/msg_sys_enumerate_stage.go | 11 ++--- network/mhfpacket/msg_sys_lock_stage.go | 23 +++++------ network/mhfpacket/msg_sys_unlock_stage.go | 12 +++--- server/channelserver/handlers.go | 6 +-- server/channelserver/handlers_stage.go | 43 +++++++++++--------- server/channelserver/sys_session.go | 1 - server/channelserver/sys_stage.go | 1 + 9 files changed, 53 insertions(+), 57 deletions(-) diff --git a/network/mhfpacket/msg_sys_create_stage.go b/network/mhfpacket/msg_sys_create_stage.go index fe6e533ff..9c11ba46c 100644 --- a/network/mhfpacket/msg_sys_create_stage.go +++ b/network/mhfpacket/msg_sys_create_stage.go @@ -3,7 +3,6 @@ package mhfpacket import ( "errors" "erupe-ce/common/byteframe" - "erupe-ce/common/bfutil" "erupe-ce/network" "erupe-ce/network/clientctx" ) @@ -13,7 +12,7 @@ type MsgSysCreateStage struct { AckHandle uint32 Unk0 uint8 // Likely only has 1 and 2 as values. PlayerCount uint8 - StageID string // NULL terminated string. + StageID string } // Opcode returns the ID associated with this packet type. @@ -26,8 +25,8 @@ func (m *MsgSysCreateStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Client m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint8() m.PlayerCount = bf.ReadUint8() - stageIDLength := bf.ReadUint8() - m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + bf.ReadUint8() // Length StageID + m.StageID = string(bf.ReadNullTerminatedBytes()) return nil } diff --git a/network/mhfpacket/msg_sys_enter_stage.go b/network/mhfpacket/msg_sys_enter_stage.go index 5a1ccb8ab..17ba468f2 100644 --- a/network/mhfpacket/msg_sys_enter_stage.go +++ b/network/mhfpacket/msg_sys_enter_stage.go @@ -11,7 +11,7 @@ import ( // MsgSysEnterStage represents the MSG_SYS_ENTER_STAGE type MsgSysEnterStage struct { AckHandle uint32 - UnkBool uint8 + Unk bool StageID string } @@ -23,8 +23,8 @@ func (m *MsgSysEnterStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysEnterStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.UnkBool = bf.ReadUint8() - bf.ReadUint8() + m.Unk = bf.ReadBool() // IsQuest? + bf.ReadUint8() // Length StageID m.StageID = string(bf.ReadNullTerminatedBytes()) return nil } diff --git a/network/mhfpacket/msg_sys_enumerate_stage.go b/network/mhfpacket/msg_sys_enumerate_stage.go index a3f125941..b0d25c099 100644 --- a/network/mhfpacket/msg_sys_enumerate_stage.go +++ b/network/mhfpacket/msg_sys_enumerate_stage.go @@ -2,8 +2,6 @@ package mhfpacket import ( "errors" - "erupe-ce/common/stringsupport" - "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" @@ -12,8 +10,7 @@ import ( // MsgSysEnumerateStage represents the MSG_SYS_ENUMERATE_STAGE type MsgSysEnumerateStage struct { AckHandle uint32 - Unk0 uint8 // Hardcoded 1 in the binary - StagePrefix string // NULL terminated string. + StagePrefix string } // Opcode returns the ID associated with this packet type. @@ -24,9 +21,9 @@ func (m *MsgSysEnumerateStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysEnumerateStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint8() - bf.ReadUint8() - m.StagePrefix = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) + bf.ReadUint8() // Always 1 + bf.ReadUint8() // Length StagePrefix + m.StagePrefix = string(bf.ReadNullTerminatedBytes()) return nil } diff --git a/network/mhfpacket/msg_sys_lock_stage.go b/network/mhfpacket/msg_sys_lock_stage.go index 14b082596..13867b825 100644 --- a/network/mhfpacket/msg_sys_lock_stage.go +++ b/network/mhfpacket/msg_sys_lock_stage.go @@ -1,20 +1,17 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgSysLockStage represents the MSG_SYS_LOCK_STAGE type MsgSysLockStage struct { - AckHandle uint32 - Unk0 uint8 // Hardcoded 1 in the binary - Unk1 uint8 // Hardcoded 1 in the binary - StageIDLength uint8 - StageID string + AckHandle uint32 + StageID string } // Opcode returns the ID associated with this packet type. @@ -25,10 +22,10 @@ func (m *MsgSysLockStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysLockStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint8() - m.Unk1 = bf.ReadUint8() - m.StageIDLength = bf.ReadUint8() - m.StageID = string(bf.ReadBytes(uint(m.StageIDLength))) + bf.ReadUint8() // Always 1 + bf.ReadUint8() // Always 1 + bf.ReadUint8() // Length StageID + m.StageID = string(bf.ReadNullTerminatedBytes()) return nil } diff --git a/network/mhfpacket/msg_sys_unlock_stage.go b/network/mhfpacket/msg_sys_unlock_stage.go index 74af57424..ec1effdc5 100644 --- a/network/mhfpacket/msg_sys_unlock_stage.go +++ b/network/mhfpacket/msg_sys_unlock_stage.go @@ -1,15 +1,14 @@ package mhfpacket import ( + "errors" + "erupe-ce/common/byteframe" "erupe-ce/network" "erupe-ce/network/clientctx" - "erupe-ce/common/byteframe" ) // MsgSysUnlockStage represents the MSG_SYS_UNLOCK_STAGE -type MsgSysUnlockStage struct { - Unk0 uint16 // Hardcoded 0 in the binary. -} +type MsgSysUnlockStage struct{} // Opcode returns the ID associated with this packet type. func (m *MsgSysUnlockStage) Opcode() network.PacketID { @@ -18,12 +17,11 @@ func (m *MsgSysUnlockStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysUnlockStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - m.Unk0 = bf.ReadUint16() + bf.ReadUint16() // Zeroed return nil } // Build builds a binary packet from the current data. func (m *MsgSysUnlockStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - bf.WriteUint16(m.Unk0) - return nil + return errors.New("NOT IMPLEMENTED") } diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index e0d162b03..abba0cfe6 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -378,7 +378,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { if session.charID == CharID { count++ sessionName := stringsupport.UTF8ToSJIS(session.Name) - sessionStage := stringsupport.UTF8ToSJIS(session.stageID) + sessionStage := stringsupport.UTF8ToSJIS(session.stage.id) resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4())) resp.WriteUint16(c.Port) resp.WriteUint32(session.charID) @@ -408,7 +408,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { if strings.Contains(session.Name, searchTerm) { count++ sessionName := stringsupport.UTF8ToSJIS(session.Name) - sessionStage := stringsupport.UTF8ToSJIS(session.stageID) + sessionStage := stringsupport.UTF8ToSJIS(session.stage.id) resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4())) resp.WriteUint16(c.Port) resp.WriteUint32(session.charID) @@ -445,7 +445,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) { hrp := uint16(1) gr := uint16(0) s.server.db.QueryRow("SELECT hrp, gr FROM characters WHERE id=$1", session.charID).Scan(&hrp, &gr) - sessionStage := stringsupport.UTF8ToSJIS(session.stageID) + sessionStage := stringsupport.UTF8ToSJIS(session.stage.id) sessionName := stringsupport.UTF8ToSJIS(session.Name) resp.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(c.IP).To4())) resp.WriteUint16(c.Port) diff --git a/server/channelserver/handlers_stage.go b/server/channelserver/handlers_stage.go index cf8757b00..7a12d453e 100644 --- a/server/channelserver/handlers_stage.go +++ b/server/channelserver/handlers_stage.go @@ -55,7 +55,6 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { // Save our new stage ID and pointer to the new stage itself. s.Lock() - s.stageID = stageID s.stage = s.server.stages[stageID] s.Unlock() @@ -153,13 +152,13 @@ func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysEnterStage) // Push our current stage ID to the movement stack before entering another one. - if s.stageID == "" { + if s.stage.id == "" { s.stageMoveStack.Set(pkt.StageID) } else { s.stage.Lock() s.stage.reservedClientSlots[s.charID] = false s.stage.Unlock() - s.stageMoveStack.Push(s.stageID) + s.stageMoveStack.Push(s.stage.id) s.stageMoveStack.Lock() } @@ -206,9 +205,12 @@ func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLockStage) - // TODO(Andoryuuta): What does this packet _actually_ do? - // I think this is supposed to mark a stage as no longer able to accept client reservations - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + if stage, exists := s.server.stages[pkt.StageID]; exists { + stage.Lock() + stage.locked = true + stage.Unlock() + } + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { @@ -218,7 +220,9 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { for charID := range s.reservationStage.reservedClientSlots { session := s.server.FindSessionByCharID(charID) - session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) + if session != nil { + session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) + } } delete(s.server.stages, s.reservationStage.id) @@ -241,6 +245,10 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) { } 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)) + return + } if len(stage.password) > 0 { if stage.password != s.stagePass { doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) @@ -383,20 +391,17 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { joinable++ bf.WriteUint16(uint16(len(stage.reservedClientSlots))) - bf.WriteUint16(0) // Unk - if len(stage.clients) > 0 { - bf.WriteUint16(1) - } else { - bf.WriteUint16(0) - } + bf.WriteUint16(uint16(len(stage.clients))) + bf.WriteUint16(uint16(len(stage.clients))) bf.WriteUint16(stage.maxPlayers) - if len(stage.password) > 0 { - // This byte has also been seen as 1 - // The quest is also recognised as locked when this is 2 - bf.WriteUint8(2) - } else { - bf.WriteUint8(0) + var flags uint8 + if stage.locked { + flags |= 1 } + if len(stage.password) > 0 { + flags |= 2 + } + bf.WriteUint8(flags) ps.Uint8(bf, sid, false) stage.RUnlock() } diff --git a/server/channelserver/sys_session.go b/server/channelserver/sys_session.go index 32004151d..5034f38c2 100644 --- a/server/channelserver/sys_session.go +++ b/server/channelserver/sys_session.go @@ -36,7 +36,6 @@ type Session struct { objectIndex uint16 userEnteredStage bool // If the user has entered a stage before - stageID string stage *Stage reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet. stagePass string // Temporary storage diff --git a/server/channelserver/sys_stage.go b/server/channelserver/sys_stage.go index ae8ddd149..dbfcbb7c3 100644 --- a/server/channelserver/sys_stage.go +++ b/server/channelserver/sys_stage.go @@ -47,6 +47,7 @@ type Stage struct { host *Session maxPlayers uint16 password string + locked bool } // NewStage creates a new stage with intialized values.