From dc874877d729498225dbc74c5cb5898db2ac1bf4 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Sun, 4 Sep 2022 01:16:15 -0400 Subject: [PATCH 1/7] Added world_name and land columns to the servers table to provide easier identification for external and internal applications utilizing the database --- main.go | 6 +++++- patch-schema/servers_info.sql | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 patch-schema/servers_info.sql diff --git a/main.go b/main.go index b9dc62538..b222e0ec9 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( "erupe-ce/server/entranceserver" "erupe-ce/server/launcherserver" "erupe-ce/server/signserver" + "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "go.uber.org/zap" @@ -173,6 +174,8 @@ func main() { ci := 0 count := 1 for _, ee := range erupeConfig.Entrance.Entries { + cn := 1 + for _, ce := range ee.Channels { sid := (4096 + si*256) + (16 + ci) c := *channelserver.NewServer(&channelserver.Config{ @@ -192,12 +195,13 @@ func main() { if err != nil { preventClose(fmt.Sprintf("Failed to start channel server: %s", err.Error())) } else { - channelQuery += fmt.Sprintf("INSERT INTO servers (server_id, season, current_players) VALUES (%d, %d, 0);", sid, si%3) + channelQuery += fmt.Sprintf("INSERT INTO servers (server_id, season, current_players, world_name, land) VALUES (%d, %d, 0, '%s', %d);", sid, si%3, ee.Name, cn) channels = append(channels, &c) logger.Info(fmt.Sprintf("Started channel server %d on port %d", count, ce.Port)) ci++ count++ } + cn++ } ci = 0 si++ diff --git a/patch-schema/servers_info.sql b/patch-schema/servers_info.sql new file mode 100644 index 000000000..6c24a035e --- /dev/null +++ b/patch-schema/servers_info.sql @@ -0,0 +1,10 @@ +--adds world_name and land columns + +CREATE TABLE IF NOT EXISTS public.servers +( + server_id integer NOT NULL, + season integer NOT NULL, + current_players integer NOT NULL, + world_name text COLLATE pg_catalog."default", + land integer +) \ No newline at end of file From 3ba56abfa8d98affe139ddf87f84df7e08816fba Mon Sep 17 00:00:00 2001 From: Eclipse Date: Sun, 4 Sep 2022 01:48:38 -0400 Subject: [PATCH 2/7] Forgot to add alter lines if table already exists --- patch-schema/servers_info.sql | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/patch-schema/servers_info.sql b/patch-schema/servers_info.sql index 6c24a035e..b01672f89 100644 --- a/patch-schema/servers_info.sql +++ b/patch-schema/servers_info.sql @@ -7,4 +7,11 @@ CREATE TABLE IF NOT EXISTS public.servers current_players integer NOT NULL, world_name text COLLATE pg_catalog."default", land integer -) \ No newline at end of file +) + + +ALTER TABLE IF EXISTS public.servers + ADD COLUMN land integer; + +ALTER TABLE IF EXISTS public.servers + ADD COLUMN world_name text COLLATE pg_catalog."default"; \ No newline at end of file From 3c096fa8d7040408973beba44480bcd7433bc925 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Sun, 4 Sep 2022 02:10:46 -0400 Subject: [PATCH 3/7] proper formating --- patch-schema/servers_info.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/patch-schema/servers_info.sql b/patch-schema/servers_info.sql index b01672f89..c514b8e12 100644 --- a/patch-schema/servers_info.sql +++ b/patch-schema/servers_info.sql @@ -1,4 +1,5 @@ --adds world_name and land columns +BEGIN; CREATE TABLE IF NOT EXISTS public.servers ( @@ -14,4 +15,6 @@ ALTER TABLE IF EXISTS public.servers ADD COLUMN land integer; ALTER TABLE IF EXISTS public.servers - ADD COLUMN world_name text COLLATE pg_catalog."default"; \ No newline at end of file + ADD COLUMN world_name text COLLATE pg_catalog."default"; + +END; \ No newline at end of file From e0176ca774454a77eca9a1dde86b3f0703a0bd85 Mon Sep 17 00:00:00 2001 From: wish Date: Sun, 4 Sep 2022 16:40:06 +1000 Subject: [PATCH 4/7] indexing changes and add world description --- main.go | 7 ++----- patch-schema/servers_info.sql | 13 ++++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index b222e0ec9..a9c796f29 100644 --- a/main.go +++ b/main.go @@ -174,9 +174,7 @@ func main() { ci := 0 count := 1 for _, ee := range erupeConfig.Entrance.Entries { - cn := 1 - - for _, ce := range ee.Channels { + for i, ce := range ee.Channels { sid := (4096 + si*256) + (16 + ci) c := *channelserver.NewServer(&channelserver.Config{ ID: uint16(sid), @@ -195,13 +193,12 @@ func main() { if err != nil { preventClose(fmt.Sprintf("Failed to start channel server: %s", err.Error())) } else { - channelQuery += fmt.Sprintf("INSERT INTO servers (server_id, season, current_players, world_name, land) VALUES (%d, %d, 0, '%s', %d);", sid, si%3, ee.Name, cn) + channelQuery += fmt.Sprintf(`INSERT INTO servers (server_id, season, current_players, world_name, world_description, land) VALUES (%d, %d, 0, '%s', '%s', %d);`, sid, si%3, ee.Name, ee.Description, i+1) channels = append(channels, &c) logger.Info(fmt.Sprintf("Started channel server %d on port %d", count, ce.Port)) ci++ count++ } - cn++ } ci = 0 si++ diff --git a/patch-schema/servers_info.sql b/patch-schema/servers_info.sql index c514b8e12..06389b6ed 100644 --- a/patch-schema/servers_info.sql +++ b/patch-schema/servers_info.sql @@ -7,14 +7,17 @@ CREATE TABLE IF NOT EXISTS public.servers season integer NOT NULL, current_players integer NOT NULL, world_name text COLLATE pg_catalog."default", + world_description text, land integer -) +); +ALTER TABLE public.servers + ADD COLUMN IF NOT EXISTS land integer; -ALTER TABLE IF EXISTS public.servers - ADD COLUMN land integer; +ALTER TABLE public.servers + ADD COLUMN IF NOT EXISTS world_name text COLLATE pg_catalog."default"; -ALTER TABLE IF EXISTS public.servers - ADD COLUMN world_name text COLLATE pg_catalog."default"; +ALTER TABLE public.servers + ADD COLUMN IF NOT EXISTS world_description text; END; \ No newline at end of file From 44a42a3365ee8c46c9ccc42b283dd33419209a17 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Sun, 18 Sep 2022 14:15:11 -0400 Subject: [PATCH 5/7] Implemented the ability to enable and disable commands in configuration as well as increased scope of the config to the entire project. --- config.json | 25 ++ config/config.go | 55 ++++ go.mod | 2 +- go.sum | 9 + main.go | 54 ++- server/channelserver/handlers_cast_binary.go | 329 +++++++++++-------- 6 files changed, 309 insertions(+), 165 deletions(-) diff --git a/config.json b/config.json index 00e541adf..505249cf1 100644 --- a/config.json +++ b/config.json @@ -30,6 +30,31 @@ "bottoken": "", "realtimeChannelID": "" }, + "ServerCommands": { + "enabled": true, + "Commands": [ + { + "name": "Rights", + "enabled": true, + "prefix": "!rights" + }, + { + "name": "Ravi", + "enabled": true, + "prefix": "!ravi" + }, + { + "name": "Tele", + "enabled": true, + "prefix": "!tele" + }, + { + "name": "Reload", + "enabled": true, + "prefix": "!reload" + } + ] + }, "database": { "host": "localhost", "port": 5432, diff --git a/config/config.go b/config/config.go index bfbf8086a..45873074b 100644 --- a/config/config.go +++ b/config/config.go @@ -1,8 +1,11 @@ package config import ( + "fmt" "log" "net" + "os" + "time" "github.com/spf13/viper" ) @@ -16,6 +19,7 @@ type Config struct { DevModeOptions DevModeOptions Discord Discord + ServerCommands ServerCommands Database Database Launcher Launcher Sign Sign @@ -59,6 +63,18 @@ type Discord struct { DevMode bool } +// Server commands +type ServerCommands struct { + Enabled bool + Commands []ServerCommand +} + +type ServerCommand struct { + Name string + Enabled bool + Prefix string +} + // Database holds the postgres database config. type Database struct { Host string @@ -107,6 +123,28 @@ 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())) + } + +} + +func GetServerCommandByName(cmdName string) ServerCommand { + var val ServerCommand + for _, c := range ErupeConfig.ServerCommands.Commands { + if c.Name == cmdName { + return c + } + } + + return val +} + // getOutboundIP4 gets the preferred outbound ip4 of this machine // From https://stackoverflow.com/a/37382208 func getOutboundIP4() net.IP { @@ -148,3 +186,20 @@ func LoadConfig() (*Config, error) { return c, nil } + +func preventClose(text string) { + if ErupeConfig.DisableSoftCrash { + os.Exit(0) + } + fmt.Println("\nFailed to start Erupe:\n" + text) + go wait() + fmt.Println("\nPress Enter/Return to exit...") + fmt.Scanln() + os.Exit(0) +} + +func wait() { + for { + time.Sleep(time.Millisecond * 100) + } +} diff --git a/go.mod b/go.mod index 8107625a2..3ac44e932 100644 --- a/go.mod +++ b/go.mod @@ -19,5 +19,5 @@ require ( golang.org/x/crypto v0.0.0-20211202192323-5770296d904e golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect golang.org/x/text v0.3.7 - golang.org/x/tools v0.1.8 // indirect + honnef.co/go/tools v0.3.3 ) diff --git a/go.sum b/go.sum index 9750b4732..91403fd95 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -295,6 +297,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8= golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -307,6 +310,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -334,6 +338,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -510,6 +515,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f h1:OKYpQQVE3DKSc3r3zHVzq46vq5YH7x8xpR3/k9ixmUg= +golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -638,6 +645,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= +honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index a9c796f29..a6074c7b2 100644 --- a/main.go +++ b/main.go @@ -20,8 +20,6 @@ import ( "go.uber.org/zap" ) -var erupeConfig *config.Config - // Temporary DB auto clean on startup for quick development & testing. func cleanDB(db *sqlx.DB) { _ = db.MustExec("DELETE FROM guild_characters") @@ -39,25 +37,19 @@ func main() { logger.Info("Starting Erupe") - // Load the configuration. - erupeConfig, err = config.LoadConfig() - if err != nil { - preventClose(fmt.Sprintf("Failed to load config: %s", err.Error())) - } - - if erupeConfig.Database.Password == "" { + if config.ErupeConfig.Database.Password == "" { preventClose("Database password is blank") } - if net.ParseIP(erupeConfig.Host) == nil { - ips, _ := net.LookupIP(erupeConfig.Host) + if net.ParseIP(config.ErupeConfig.Host) == nil { + ips, _ := net.LookupIP(config.ErupeConfig.Host) for _, ip := range ips { if ip != nil { - erupeConfig.Host = ip.String() + config.ErupeConfig.Host = ip.String() break } } - if net.ParseIP(erupeConfig.Host) == nil { + if net.ParseIP(config.ErupeConfig.Host) == nil { preventClose("Invalid host address") } } @@ -65,10 +57,10 @@ func main() { // Discord bot var discordBot *discordbot.DiscordBot = nil - if erupeConfig.Discord.Enabled { + if config.ErupeConfig.Discord.Enabled { bot, err := discordbot.NewDiscordBot(discordbot.Options{ Logger: logger, - Config: erupeConfig, + Config: config.ErupeConfig, }) if err != nil { @@ -91,11 +83,11 @@ func main() { // Create the postgres DB pool. connectString := fmt.Sprintf( "host=%s port=%d user=%s password=%s dbname= %s sslmode=disable", - erupeConfig.Database.Host, - erupeConfig.Database.Port, - erupeConfig.Database.User, - erupeConfig.Database.Password, - erupeConfig.Database.Database, + config.ErupeConfig.Database.Host, + config.ErupeConfig.Database.Port, + config.ErupeConfig.Database.User, + config.ErupeConfig.Database.Password, + config.ErupeConfig.Database.Database, ) db, err := sqlx.Open("postgres", connectString) @@ -117,7 +109,7 @@ func main() { _ = db.MustExec("UPDATE characters SET cafe_time=0") // Clean the DB if the option is on. - if erupeConfig.DevMode && erupeConfig.DevModeOptions.CleanDB { + if config.ErupeConfig.DevMode && config.ErupeConfig.DevModeOptions.CleanDB { logger.Info("Cleaning DB") cleanDB(db) logger.Info("Done cleaning DB") @@ -127,13 +119,13 @@ func main() { // Launcher HTTP server. var launcherServer *launcherserver.Server - if erupeConfig.DevMode && erupeConfig.DevModeOptions.EnableLauncherServer { + if config.ErupeConfig.DevMode && config.ErupeConfig.DevModeOptions.EnableLauncherServer { launcherServer = launcherserver.NewServer( &launcherserver.Config{ Logger: logger.Named("launcher"), - ErupeConfig: erupeConfig, + ErupeConfig: config.ErupeConfig, DB: db, - UseOriginalLauncherFiles: erupeConfig.Launcher.UseOriginalLauncherFiles, + UseOriginalLauncherFiles: config.ErupeConfig.Launcher.UseOriginalLauncherFiles, }) err = launcherServer.Start() if err != nil { @@ -146,7 +138,7 @@ func main() { entranceServer := entranceserver.NewServer( &entranceserver.Config{ Logger: logger.Named("entrance"), - ErupeConfig: erupeConfig, + ErupeConfig: config.ErupeConfig, DB: db, }) err = entranceServer.Start() @@ -159,7 +151,7 @@ func main() { signServer := signserver.NewServer( &signserver.Config{ Logger: logger.Named("sign"), - ErupeConfig: erupeConfig, + ErupeConfig: config.ErupeConfig, DB: db, }) err = signServer.Start() @@ -173,18 +165,18 @@ func main() { si := 0 ci := 0 count := 1 - for _, ee := range erupeConfig.Entrance.Entries { + for _, ee := range config.ErupeConfig.Entrance.Entries { for i, ce := range ee.Channels { sid := (4096 + si*256) + (16 + ci) c := *channelserver.NewServer(&channelserver.Config{ ID: uint16(sid), Logger: logger.Named("channel-" + fmt.Sprint(count)), - ErupeConfig: erupeConfig, + ErupeConfig: config.ErupeConfig, DB: db, DiscordBot: discordBot, }) if ee.IP == "" { - c.IP = erupeConfig.Host + c.IP = config.ErupeConfig.Host } else { c.IP = ee.IP } @@ -223,7 +215,7 @@ func main() { } signServer.Shutdown() entranceServer.Shutdown() - if erupeConfig.DevModeOptions.EnableLauncherServer { + if config.ErupeConfig.DevModeOptions.EnableLauncherServer { launcherServer.Shutdown() } @@ -237,7 +229,7 @@ func wait() { } func preventClose(text string) { - if erupeConfig.DisableSoftCrash { + if config.ErupeConfig.DisableSoftCrash { os.Exit(0) } fmt.Println("\nFailed to start Erupe:\n" + text) diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 35538e0fb..35c9adf0c 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -8,8 +8,11 @@ import ( "time" "erupe-ce/common/byteframe" + "erupe-ce/config" "erupe-ce/network/binpacket" "erupe-ce/network/mhfpacket" + + "go.uber.org/zap" ) // MSG_SYS_CAST[ED]_BINARY types enum @@ -29,6 +32,47 @@ const ( BroadcastTypeWorld = 0x0a ) +var raviCmd config.ServerCommand +var rightsCmd config.ServerCommand +var teleCmd config.ServerCommand +var reloadCmd config.ServerCommand +var logger *zap.Logger + +func init() { + zapLogger, _ := zap.NewDevelopment() + defer zapLogger.Sync() + logger = zapLogger.Named("channelserver") + + raviCmd = config.GetServerCommandByName("Ravi") + if raviCmd.Enabled { + logger.Info(raviCmd.Name + " command is enabled") + } else { + logger.Info(raviCmd.Name + " command is disabled") + } + + rightsCmd = config.GetServerCommandByName("Rights") + if rightsCmd.Enabled { + logger.Info(rightsCmd.Name + " command is enabled") + } else { + logger.Info(rightsCmd.Name + " command is disabled") + } + + teleCmd = config.GetServerCommandByName("Tele") + if teleCmd.Enabled { + logger.Info(teleCmd.Name + " command is enabled") + } else { + logger.Info(teleCmd.Name + " command is disabled") + } + + reloadCmd = config.GetServerCommandByName("Reload") + if reloadCmd.Enabled { + logger.Info(reloadCmd.Name + " command is enabled") + } else { + logger.Info(reloadCmd.Name + " command is disabled") + } + +} + func sendServerChatMessage(s *Session, message string) { // Make the inside of the casted binary bf := byteframe.NewByteFrame() @@ -165,78 +209,88 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { fmt.Printf("Got chat message: %+v\n", chatMessage) - // Flush all objects and users and reload - if strings.HasPrefix(chatMessage.Message, "!reload") { - sendServerChatMessage(s, "Reloading players...") - var temp mhfpacket.MHFPacket - deleteNotif := byteframe.NewByteFrame() - for _, object := range s.stage.objects { - if object.ownerCharID == s.charID { - continue + if strings.HasPrefix(chatMessage.Message, reloadCmd.Prefix) { + // Flush all objects and users and reload + if reloadCmd.Enabled { + sendServerChatMessage(s, "Reloading players...") + var temp mhfpacket.MHFPacket + deleteNotif := byteframe.NewByteFrame() + for _, object := range s.stage.objects { + if object.ownerCharID == s.charID { + continue + } + temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id} + deleteNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(deleteNotif, s.clientContext) } - temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id} - deleteNotif.WriteUint16(uint16(temp.Opcode())) - temp.Build(deleteNotif, s.clientContext) - } - for _, session := range s.server.sessions { - if s == session { - continue + for _, session := range s.server.sessions { + if s == session { + continue + } + temp = &mhfpacket.MsgSysDeleteUser{CharID: session.charID} + deleteNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(deleteNotif, s.clientContext) } - temp = &mhfpacket.MsgSysDeleteUser{CharID: session.charID} - deleteNotif.WriteUint16(uint16(temp.Opcode())) - temp.Build(deleteNotif, s.clientContext) - } - deleteNotif.WriteUint16(0x0010) - s.QueueSend(deleteNotif.Data()) - time.Sleep(500 * time.Millisecond) - reloadNotif := byteframe.NewByteFrame() - for _, session := range s.server.sessions { - if s == session { - continue + deleteNotif.WriteUint16(0x0010) + s.QueueSend(deleteNotif.Data()) + time.Sleep(500 * time.Millisecond) + reloadNotif := byteframe.NewByteFrame() + for _, session := range s.server.sessions { + if s == session { + continue + } + temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} + reloadNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(reloadNotif, s.clientContext) + for i := 0; i < 3; i++ { + temp = &mhfpacket.MsgSysNotifyUserBinary{ + CharID: session.charID, + BinaryType: uint8(i + 1), + } + reloadNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(reloadNotif, s.clientContext) + } } - temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} - reloadNotif.WriteUint16(uint16(temp.Opcode())) - temp.Build(reloadNotif, s.clientContext) - for i := 0; i < 3; i++ { - temp = &mhfpacket.MsgSysNotifyUserBinary{ - CharID: session.charID, - BinaryType: uint8(i + 1), + for _, obj := range s.stage.objects { + if obj.ownerCharID == s.charID { + continue + } + temp = &mhfpacket.MsgSysDuplicateObject{ + ObjID: obj.id, + X: obj.x, + Y: obj.y, + Z: obj.z, + Unk0: 0, + OwnerCharID: obj.ownerCharID, } reloadNotif.WriteUint16(uint16(temp.Opcode())) temp.Build(reloadNotif, s.clientContext) } + reloadNotif.WriteUint16(0x0010) + s.QueueSend(reloadNotif.Data()) + } else { + sendServerChatMessage(s, reloadCmd.Name+" command is disabled") } - for _, obj := range s.stage.objects { - if obj.ownerCharID == s.charID { - continue - } - temp = &mhfpacket.MsgSysDuplicateObject{ - ObjID: obj.id, - X: obj.x, - Y: obj.y, - Z: obj.z, - Unk0: 0, - OwnerCharID: obj.ownerCharID, - } - reloadNotif.WriteUint16(uint16(temp.Opcode())) - temp.Build(reloadNotif, s.clientContext) - } - reloadNotif.WriteUint16(0x0010) - s.QueueSend(reloadNotif.Data()) + } - // Set account rights - if strings.HasPrefix(chatMessage.Message, "!rights") { - var v uint32 - n, err := fmt.Sscanf(chatMessage.Message, "!rights %d", &v) - if err != nil || n != 1 { - sendServerChatMessage(s, "Error in command. Format: !rights n") - } else { - _, 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) - if err == nil { - sendServerChatMessage(s, fmt.Sprintf("Set rights integer: %d", v)) + if strings.HasPrefix(chatMessage.Message, rightsCmd.Prefix) { + // Set account rights + if rightsCmd.Enabled { + var v uint32 + n, err := fmt.Sscanf(chatMessage.Message, "!rights %d", &v) + if err != nil || n != 1 { + sendServerChatMessage(s, "Error in command. Format: !rights n") + } else { + _, 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) + if err == nil { + sendServerChatMessage(s, fmt.Sprintf("Set rights integer: %d", v)) + } } + } else { + sendServerChatMessage(s, rightsCmd.Name+" command is disabled") } + } // Discord integration @@ -244,88 +298,97 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { s.server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message) } - // RAVI COMMANDS V2 - if strings.HasPrefix(chatMessage.Message, "!ravi") { - if getRaviSemaphore(s) != "" { - s.server.raviente.Lock() - if !strings.HasPrefix(chatMessage.Message, "!ravi ") { - sendServerChatMessage(s, "No Raviente command specified!") - } else { - if strings.HasPrefix(chatMessage.Message, "!ravi start") { - if s.server.raviente.register.startTime == 0 { - s.server.raviente.register.startTime = s.server.raviente.register.postTime - sendServerChatMessage(s, "The Great Slaying will begin in a moment") - s.notifyRavi() - } else { - sendServerChatMessage(s, "The Great Slaying has already begun!") - } - } else if strings.HasPrefix(chatMessage.Message, "!ravi sm") || strings.HasPrefix(chatMessage.Message, "!ravi setmultiplier") { - var num uint16 - n, numerr := fmt.Sscanf(chatMessage.Message, "!ravi sm %d", &num) - if numerr != nil || n != 1 { - sendServerChatMessage(s, "Error in command. Format: !ravi sm n") - } else if s.server.raviente.state.damageMultiplier == 1 { - if num > 32 { - sendServerChatMessage(s, "Raviente multiplier too high, defaulting to 32x") - s.server.raviente.state.damageMultiplier = 32 - } else { - sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier set to %dx", num)) - s.server.raviente.state.damageMultiplier = uint32(num) - } - } else { - sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier is already set to %dx!", s.server.raviente.state.damageMultiplier)) - } - } else if strings.HasPrefix(chatMessage.Message, "!ravi cm") || strings.HasPrefix(chatMessage.Message, "!ravi checkmultiplier") { - sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier is currently %dx", s.server.raviente.state.damageMultiplier)) - } else if strings.HasPrefix(chatMessage.Message, "!ravi sr") || strings.HasPrefix(chatMessage.Message, "!ravi sendres") { - if s.server.raviente.state.stateData[28] > 0 { - sendServerChatMessage(s, "Sending resurrection support!") - s.server.raviente.state.stateData[28] = 0 - } else { - sendServerChatMessage(s, "Resurrection support has not been requested!") - } - } else if strings.HasPrefix(chatMessage.Message, "!ravi ss") || strings.HasPrefix(chatMessage.Message, "!ravi sendsed") { - sendServerChatMessage(s, "Sending sedation support if requested!") - // Total BerRavi HP - HP := s.server.raviente.state.stateData[0] + s.server.raviente.state.stateData[1] + s.server.raviente.state.stateData[2] + s.server.raviente.state.stateData[3] + s.server.raviente.state.stateData[4] - s.server.raviente.support.supportData[1] = HP - } else if strings.HasPrefix(chatMessage.Message, "!ravi rs") || strings.HasPrefix(chatMessage.Message, "!ravi reqsed") { - sendServerChatMessage(s, "Requesting sedation support!") - // Total BerRavi HP - HP := s.server.raviente.state.stateData[0] + s.server.raviente.state.stateData[1] + s.server.raviente.state.stateData[2] + s.server.raviente.state.stateData[3] + s.server.raviente.state.stateData[4] - s.server.raviente.support.supportData[1] = HP + 12 + if strings.HasPrefix(chatMessage.Message, raviCmd.Prefix) { + // RAVI COMMANDS V2 + if raviCmd.Enabled { + if getRaviSemaphore(s) != "" { + s.server.raviente.Lock() + if !strings.HasPrefix(chatMessage.Message, "!ravi ") { + sendServerChatMessage(s, "No Raviente command specified!") } else { - sendServerChatMessage(s, "Raviente command not recognised!") + if strings.HasPrefix(chatMessage.Message, "!ravi start") { + if s.server.raviente.register.startTime == 0 { + s.server.raviente.register.startTime = s.server.raviente.register.postTime + sendServerChatMessage(s, "The Great Slaying will begin in a moment") + s.notifyRavi() + } else { + sendServerChatMessage(s, "The Great Slaying has already begun!") + } + } else if strings.HasPrefix(chatMessage.Message, "!ravi sm") || strings.HasPrefix(chatMessage.Message, "!ravi setmultiplier") { + var num uint16 + n, numerr := fmt.Sscanf(chatMessage.Message, "!ravi sm %d", &num) + if numerr != nil || n != 1 { + sendServerChatMessage(s, "Error in command. Format: !ravi sm n") + } else if s.server.raviente.state.damageMultiplier == 1 { + if num > 32 { + sendServerChatMessage(s, "Raviente multiplier too high, defaulting to 32x") + s.server.raviente.state.damageMultiplier = 32 + } else { + sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier set to %dx", num)) + s.server.raviente.state.damageMultiplier = uint32(num) + } + } else { + sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier is already set to %dx!", s.server.raviente.state.damageMultiplier)) + } + } else if strings.HasPrefix(chatMessage.Message, "!ravi cm") || strings.HasPrefix(chatMessage.Message, "!ravi checkmultiplier") { + sendServerChatMessage(s, fmt.Sprintf("Raviente multiplier is currently %dx", s.server.raviente.state.damageMultiplier)) + } else if strings.HasPrefix(chatMessage.Message, "!ravi sr") || strings.HasPrefix(chatMessage.Message, "!ravi sendres") { + if s.server.raviente.state.stateData[28] > 0 { + sendServerChatMessage(s, "Sending resurrection support!") + s.server.raviente.state.stateData[28] = 0 + } else { + sendServerChatMessage(s, "Resurrection support has not been requested!") + } + } else if strings.HasPrefix(chatMessage.Message, "!ravi ss") || strings.HasPrefix(chatMessage.Message, "!ravi sendsed") { + sendServerChatMessage(s, "Sending sedation support if requested!") + // Total BerRavi HP + HP := s.server.raviente.state.stateData[0] + s.server.raviente.state.stateData[1] + s.server.raviente.state.stateData[2] + s.server.raviente.state.stateData[3] + s.server.raviente.state.stateData[4] + s.server.raviente.support.supportData[1] = HP + } else if strings.HasPrefix(chatMessage.Message, "!ravi rs") || strings.HasPrefix(chatMessage.Message, "!ravi reqsed") { + sendServerChatMessage(s, "Requesting sedation support!") + // Total BerRavi HP + HP := s.server.raviente.state.stateData[0] + s.server.raviente.state.stateData[1] + s.server.raviente.state.stateData[2] + s.server.raviente.state.stateData[3] + s.server.raviente.state.stateData[4] + s.server.raviente.support.supportData[1] = HP + 12 + } else { + sendServerChatMessage(s, "Raviente command not recognised!") + } } + s.server.raviente.Unlock() + } else { + sendServerChatMessage(s, "No one has joined the Great Slaying!") } - s.server.raviente.Unlock() } else { - sendServerChatMessage(s, "No one has joined the Great Slaying!") + sendServerChatMessage(s, raviCmd.Name+" command is disabled") } } + // END RAVI COMMANDS V2 - if strings.HasPrefix(chatMessage.Message, "!tele ") { - var x, y int16 - n, err := fmt.Sscanf(chatMessage.Message, "!tele %d %d", &x, &y) - if err != nil || n != 2 { - sendServerChatMessage(s, "Invalid command. Usage:\"!tele 500 500\"") + if strings.HasPrefix(chatMessage.Message, teleCmd.Prefix) { + if teleCmd.Enabled { + var x, y int16 + n, err := fmt.Sscanf(chatMessage.Message, "!tele %d %d", &x, &y) + if err != nil || n != 2 { + sendServerChatMessage(s, "Invalid command. Usage:\"!tele 500 500\"") + } else { + sendServerChatMessage(s, fmt.Sprintf("Teleporting to %d %d", x, y)) + + // Make the inside of the casted binary + payload := byteframe.NewByteFrame() + payload.SetLE() + payload.WriteUint8(2) // SetState type(position == 2) + payload.WriteInt16(x) // X + payload.WriteInt16(y) // Y + payloadBytes := payload.Data() + + s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{ + CharID: s.charID, + MessageType: BinaryMessageTypeState, + RawDataPayload: payloadBytes, + }) + } } else { - sendServerChatMessage(s, fmt.Sprintf("Teleporting to %d %d", x, y)) - - // Make the inside of the casted binary - payload := byteframe.NewByteFrame() - payload.SetLE() - payload.WriteUint8(2) // SetState type(position == 2) - payload.WriteInt16(x) // X - payload.WriteInt16(y) // Y - payloadBytes := payload.Data() - - s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{ - CharID: s.charID, - MessageType: BinaryMessageTypeState, - RawDataPayload: payloadBytes, - }) + sendServerChatMessage(s, teleCmd.Name+" command is disabled") } } } From 2f123d96df3904571004e4cedd8b8c1faee0a8a3 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Thu, 22 Sep 2022 20:51:18 -0400 Subject: [PATCH 6/7] Implemented the ability to enable/disable entrance, sign, and channel servers --- config.json | 6 ++ config/config.go | 10 +++- go.mod | 2 +- go.sum | 23 ++------ main.go | 144 +++++++++++++++++++++++++++-------------------- 5 files changed, 103 insertions(+), 82 deletions(-) diff --git a/config.json b/config.json index 505249cf1..8d500907c 100644 --- a/config.json +++ b/config.json @@ -63,13 +63,19 @@ "database": "erupe" }, "launcher": { + "enabled": true, "port": 80, "UseOriginalLauncherFiles": false }, "sign": { + "enabled": true, "port": 53312 }, + "channel": { + "enabled": true + }, "entrance": { + "enabled": true, "port": 53310, "entries": [ { diff --git a/config/config.go b/config/config.go index 45873074b..27bcff6f0 100644 --- a/config/config.go +++ b/config/config.go @@ -23,6 +23,7 @@ type Config struct { Database Database Launcher Launcher Sign Sign + Channel Channel Entrance Entrance } @@ -86,17 +87,24 @@ type Database struct { // Launcher holds the launcher server config. type Launcher struct { + Enabled bool Port int UseOriginalLauncherFiles bool } // Sign holds the sign server config. type Sign struct { - Port int + Enabled bool + Port int +} + +type Channel struct { + Enabled bool } // Entrance holds the entrance server config. type Entrance struct { + Enabled bool Port uint16 Entries []EntranceServerInfo } diff --git a/go.mod b/go.mod index 3ac44e932..f4e7f1033 100644 --- a/go.mod +++ b/go.mod @@ -19,5 +19,5 @@ require ( golang.org/x/crypto v0.0.0-20211202192323-5770296d904e golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect golang.org/x/text v0.3.7 - honnef.co/go/tools v0.3.3 + golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f // indirect ) diff --git a/go.sum b/go.sum index 91403fd95..1e7747306 100644 --- a/go.sum +++ b/go.sum @@ -38,8 +38,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -80,9 +78,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -191,9 +188,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -204,9 +200,8 @@ github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaW github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= -github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -224,9 +219,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -310,7 +304,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -337,7 +330,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -513,8 +505,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f h1:OKYpQQVE3DKSc3r3zHVzq46vq5YH7x8xpR3/k9ixmUg= golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -624,9 +614,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -645,8 +634,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= -honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index a6074c7b2..60b64dac1 100644 --- a/main.go +++ b/main.go @@ -135,72 +135,83 @@ func main() { } // Entrance server. - entranceServer := entranceserver.NewServer( - &entranceserver.Config{ - Logger: logger.Named("entrance"), - ErupeConfig: config.ErupeConfig, - DB: db, - }) - err = entranceServer.Start() - if err != nil { - preventClose(fmt.Sprintf("Failed to start entrance server: %s", err.Error())) - } - logger.Info("Started entrance server") - // Sign server. - signServer := signserver.NewServer( - &signserver.Config{ - Logger: logger.Named("sign"), - ErupeConfig: config.ErupeConfig, - DB: db, - }) - err = signServer.Start() - if err != nil { - preventClose(fmt.Sprintf("Failed to start sign server: %s", err.Error())) - } - logger.Info("Started sign server") - - var channels []*channelserver.Server - channelQuery := "" - si := 0 - ci := 0 - count := 1 - for _, ee := range config.ErupeConfig.Entrance.Entries { - for i, ce := range ee.Channels { - sid := (4096 + si*256) + (16 + ci) - c := *channelserver.NewServer(&channelserver.Config{ - ID: uint16(sid), - Logger: logger.Named("channel-" + fmt.Sprint(count)), + var entranceServer *entranceserver.Server + if config.ErupeConfig.Entrance.Enabled { + entranceServer = entranceserver.NewServer( + &entranceserver.Config{ + Logger: logger.Named("entrance"), ErupeConfig: config.ErupeConfig, DB: db, - DiscordBot: discordBot, }) - if ee.IP == "" { - c.IP = config.ErupeConfig.Host - } else { - c.IP = ee.IP - } - c.Port = ce.Port - err = c.Start() - if err != nil { - preventClose(fmt.Sprintf("Failed to start channel server: %s", err.Error())) - } else { - channelQuery += fmt.Sprintf(`INSERT INTO servers (server_id, season, current_players, world_name, world_description, land) VALUES (%d, %d, 0, '%s', '%s', %d);`, sid, si%3, ee.Name, ee.Description, i+1) - channels = append(channels, &c) - logger.Info(fmt.Sprintf("Started channel server %d on port %d", count, ce.Port)) - ci++ - count++ - } + err = entranceServer.Start() + if err != nil { + preventClose(fmt.Sprintf("Failed to start entrance server: %s", err.Error())) } - ci = 0 - si++ + logger.Info("Started entrance server") } - // Register all servers in DB - _ = db.MustExec(channelQuery) + // Sign server. - for _, c := range channels { - c.Channels = channels + var signServer *signserver.Server + if config.ErupeConfig.Sign.Enabled { + signServer = signserver.NewServer( + &signserver.Config{ + Logger: logger.Named("sign"), + ErupeConfig: config.ErupeConfig, + DB: db, + }) + err = signServer.Start() + if err != nil { + preventClose(fmt.Sprintf("Failed to start sign server: %s", err.Error())) + } + logger.Info("Started sign server") + } + + var channels []*channelserver.Server + + if config.ErupeConfig.Channel.Enabled { + channelQuery := "" + si := 0 + ci := 0 + count := 1 + for _, ee := range config.ErupeConfig.Entrance.Entries { + for i, ce := range ee.Channels { + sid := (4096 + si*256) + (16 + ci) + c := *channelserver.NewServer(&channelserver.Config{ + ID: uint16(sid), + Logger: logger.Named("channel-" + fmt.Sprint(count)), + ErupeConfig: config.ErupeConfig, + DB: db, + DiscordBot: discordBot, + }) + if ee.IP == "" { + c.IP = config.ErupeConfig.Host + } else { + c.IP = ee.IP + } + c.Port = ce.Port + err = c.Start() + if err != nil { + preventClose(fmt.Sprintf("Failed to start channel server: %s", err.Error())) + } else { + channelQuery += fmt.Sprintf(`INSERT INTO servers (server_id, season, current_players, world_name, world_description, land) VALUES (%d, %d, 0, '%s', '%s', %d);`, sid, si%3, ee.Name, ee.Description, i+1) + channels = append(channels, &c) + logger.Info(fmt.Sprintf("Started channel server %d on port %d", count, ce.Port)) + ci++ + count++ + } + } + ci = 0 + si++ + } + + // Register all servers in DB + _ = db.MustExec(channelQuery) + + for _, c := range channels { + c.Channels = channels + } } // Wait for exit or interrupt with ctrl+C. @@ -210,11 +221,20 @@ func main() { logger.Info("Trying to shutdown gracefully") - for _, c := range channels { - c.Shutdown() + if config.ErupeConfig.Channel.Enabled { + for _, c := range channels { + c.Shutdown() + } } - signServer.Shutdown() - entranceServer.Shutdown() + + if config.ErupeConfig.Sign.Enabled { + signServer.Shutdown() + } + + if config.ErupeConfig.Entrance.Enabled { + entranceServer.Shutdown() + } + if config.ErupeConfig.DevModeOptions.EnableLauncherServer { launcherServer.Shutdown() } From 9b1f3f80120bb684b274920accce647782d3d2cf Mon Sep 17 00:00:00 2001 From: wish Date: Fri, 30 Sep 2022 02:54:37 +1000 Subject: [PATCH 7/7] revise command rework --- config.json | 44 +++++----- config/config.go | 22 +---- server/channelserver/handlers_cast_binary.go | 86 +++++++------------- 3 files changed, 53 insertions(+), 99 deletions(-) diff --git a/config.json b/config.json index 8d500907c..5f04778c1 100644 --- a/config.json +++ b/config.json @@ -30,31 +30,25 @@ "bottoken": "", "realtimeChannelID": "" }, - "ServerCommands": { - "enabled": true, - "Commands": [ - { - "name": "Rights", - "enabled": true, - "prefix": "!rights" - }, - { - "name": "Ravi", - "enabled": true, - "prefix": "!ravi" - }, - { - "name": "Tele", - "enabled": true, - "prefix": "!tele" - }, - { - "name": "Reload", - "enabled": true, - "prefix": "!reload" - } - ] - }, + "Commands": [ + { + "name": "Rights", + "enabled": true, + "prefix": "!rights" + }, { + "name": "Raviente", + "enabled": true, + "prefix": "!ravi" + }, { + "name": "Teleport", + "enabled": true, + "prefix": "!tele" + }, { + "name": "Reload", + "enabled": true, + "prefix": "!reload" + } + ], "database": { "host": "localhost", "port": 5432, diff --git a/config/config.go b/config/config.go index 27bcff6f0..5355b6e42 100644 --- a/config/config.go +++ b/config/config.go @@ -19,7 +19,7 @@ type Config struct { DevModeOptions DevModeOptions Discord Discord - ServerCommands ServerCommands + Commands []Command Database Database Launcher Launcher Sign Sign @@ -64,13 +64,8 @@ type Discord struct { DevMode bool } -// Server commands -type ServerCommands struct { - Enabled bool - Commands []ServerCommand -} - -type ServerCommand struct { +// Command is a channelserver chat command +type Command struct { Name string Enabled bool Prefix string @@ -142,17 +137,6 @@ func init() { } -func GetServerCommandByName(cmdName string) ServerCommand { - var val ServerCommand - for _, c := range ErupeConfig.ServerCommands.Commands { - if c.Name == cmdName { - return c - } - } - - return val -} - // getOutboundIP4 gets the preferred outbound ip4 of this machine // From https://stackoverflow.com/a/37382208 func getOutboundIP4() net.IP { diff --git a/server/channelserver/handlers_cast_binary.go b/server/channelserver/handlers_cast_binary.go index 35c9adf0c..6910a01ae 100644 --- a/server/channelserver/handlers_cast_binary.go +++ b/server/channelserver/handlers_cast_binary.go @@ -32,45 +32,26 @@ const ( BroadcastTypeWorld = 0x0a ) -var raviCmd config.ServerCommand -var rightsCmd config.ServerCommand -var teleCmd config.ServerCommand -var reloadCmd config.ServerCommand -var logger *zap.Logger +var commands map[string]config.Command func init() { + commands = make(map[string]config.Command) zapLogger, _ := zap.NewDevelopment() defer zapLogger.Sync() - logger = zapLogger.Named("channelserver") - - raviCmd = config.GetServerCommandByName("Ravi") - if raviCmd.Enabled { - logger.Info(raviCmd.Name + " command is enabled") - } else { - logger.Info(raviCmd.Name + " command is disabled") - } - - rightsCmd = config.GetServerCommandByName("Rights") - if rightsCmd.Enabled { - logger.Info(rightsCmd.Name + " command is enabled") - } else { - logger.Info(rightsCmd.Name + " command is disabled") - } - - teleCmd = config.GetServerCommandByName("Tele") - if teleCmd.Enabled { - logger.Info(teleCmd.Name + " command is enabled") - } else { - logger.Info(teleCmd.Name + " command is disabled") - } - - reloadCmd = config.GetServerCommandByName("Reload") - if reloadCmd.Enabled { - logger.Info(reloadCmd.Name + " command is enabled") - } else { - logger.Info(reloadCmd.Name + " command is disabled") + logger := zapLogger.Named("commands") + cmds := config.ErupeConfig.Commands + for _, cmd := range cmds { + commands[cmd.Name] = cmd + if cmd.Enabled { + logger.Info(fmt.Sprintf("%s command is enabled, prefix: %s", cmd.Name, cmd.Prefix)) + } else { + logger.Info(fmt.Sprintf("%s command is disabled", cmd.Name)) + } } +} +func sendDisabledCommandMessage(s *Session, cmd config.Command) { + sendServerChatMessage(s, fmt.Sprintf("%s command is disabled", cmd.Name)) } func sendServerChatMessage(s *Session, message string) { @@ -209,9 +190,14 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { fmt.Printf("Got chat message: %+v\n", chatMessage) - if strings.HasPrefix(chatMessage.Message, reloadCmd.Prefix) { + // Discord integration + if (pkt.BroadcastType == BroadcastTypeStage && s.stage.id == "sl1Ns200p0a0u0") || pkt.BroadcastType == BroadcastTypeWorld { + s.server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message) + } + + if strings.HasPrefix(chatMessage.Message, commands["Reload"].Prefix) { // Flush all objects and users and reload - if reloadCmd.Enabled { + if commands["Reload"].Enabled { sendServerChatMessage(s, "Reloading players...") var temp mhfpacket.MHFPacket deleteNotif := byteframe.NewByteFrame() @@ -269,14 +255,13 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { reloadNotif.WriteUint16(0x0010) s.QueueSend(reloadNotif.Data()) } else { - sendServerChatMessage(s, reloadCmd.Name+" command is disabled") + sendDisabledCommandMessage(s, commands["Reload"]) } - } - if strings.HasPrefix(chatMessage.Message, rightsCmd.Prefix) { + if strings.HasPrefix(chatMessage.Message, commands["Rights"].Prefix) { // Set account rights - if rightsCmd.Enabled { + if commands["Rights"].Enabled { var v uint32 n, err := fmt.Sscanf(chatMessage.Message, "!rights %d", &v) if err != nil || n != 1 { @@ -288,19 +273,12 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { } } } else { - sendServerChatMessage(s, rightsCmd.Name+" command is disabled") + sendDisabledCommandMessage(s, commands["Rights"]) } - } - // Discord integration - if (pkt.BroadcastType == BroadcastTypeStage && s.stage.id == "sl1Ns200p0a0u0") || pkt.BroadcastType == BroadcastTypeWorld { - s.server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message) - } - - if strings.HasPrefix(chatMessage.Message, raviCmd.Prefix) { - // RAVI COMMANDS V2 - if raviCmd.Enabled { + if strings.HasPrefix(chatMessage.Message, commands["Raviente"].Prefix) { + if commands["Raviente"].Enabled { if getRaviSemaphore(s) != "" { s.server.raviente.Lock() if !strings.HasPrefix(chatMessage.Message, "!ravi ") { @@ -358,14 +336,12 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { sendServerChatMessage(s, "No one has joined the Great Slaying!") } } else { - sendServerChatMessage(s, raviCmd.Name+" command is disabled") + sendDisabledCommandMessage(s, commands["Raviente"]) } } - // END RAVI COMMANDS V2 - - if strings.HasPrefix(chatMessage.Message, teleCmd.Prefix) { - if teleCmd.Enabled { + if strings.HasPrefix(chatMessage.Message, commands["Teleport"].Prefix) { + if commands["Teleport"].Enabled { var x, y int16 n, err := fmt.Sscanf(chatMessage.Message, "!tele %d %d", &x, &y) if err != nil || n != 2 { @@ -388,7 +364,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { }) } } else { - sendServerChatMessage(s, teleCmd.Name+" command is disabled") + sendDisabledCommandMessage(s, commands["Teleport"]) } } }