From 8ec53aca7aedf7af3315d6be1ae774ade90ce1ad Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Sun, 21 Aug 2022 21:27:23 +0100 Subject: [PATCH] Server regions (#18867) --- .../sections/system_configuration.dm | 8 +++++ code/game/world.dm | 9 +++-- code/modules/client/client_procs.dm | 33 +++++++++++++++++++ .../login_processing/10-load_preferences.dm | 5 ++- code/modules/client/preference/preferences.dm | 2 ++ .../client/preference/preferences_mysql.dm | 10 +++++- config/example/config.toml | 6 ++++ 7 files changed, 69 insertions(+), 4 deletions(-) diff --git a/code/controllers/configuration/sections/system_configuration.dm b/code/controllers/configuration/sections/system_configuration.dm index 075f46b5771..1351da3643f 100644 --- a/code/controllers/configuration/sections/system_configuration.dm +++ b/code/controllers/configuration/sections/system_configuration.dm @@ -28,6 +28,8 @@ var/external_tos_handler = FALSE /// Map datum of the map to use, overriding the defaults, and `data/next_map.txt` var/override_map = null + /// Assoc list of region names and their server IPs. Used for geo-routing. + var/list/region_map = list() /datum/configuration_section/system_configuration/load_data(list/data) // Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line @@ -48,3 +50,9 @@ CONFIG_LOAD_STR(internal_ip, data["internal_ip"]) CONFIG_LOAD_STR(override_map, data["override_map"]) + + // Load region overrides + if(islist(data["regional_servers"])) + region_map.Cut() + for(var/list/kvset in data["regional_servers"]) + region_map[kvset["name"]] = kvset["ip"] diff --git a/code/game/world.dm b/code/game/world.dm index 16bcfea989c..a62f7395050 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -159,8 +159,13 @@ GLOBAL_LIST_EMPTY(world_topic_handlers) // Send the reboot banner to all players for(var/client/C in GLOB.clients) C << output(list2params(list(secs_before_auto_reconnect)), "browseroutput:reboot") - if(GLOB.configuration.url.server_url) // If you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite - C << link("byond://[GLOB.configuration.url.server_url]") + if(C.prefs.server_region) + // Keep them on the same relay + C << link(GLOB.configuration.system.region_map[C.prefs.server_region]) + else + // Use the default + if(GLOB.configuration.url.server_url) // If you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite + C << link("byond://[GLOB.configuration.url.server_url]") // And begin the real shutdown rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss. diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 81583716b9a..20adff91cd8 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -417,6 +417,9 @@ if(karmaholder) karmaholder.processRefunds(mob) + // Tell client about their connection + to_chat(src, "You are currently connected [prefs.server_region ? "via the [prefs.server_region] relay" : "directly"] to Paradise.") + to_chat(src, "You can change this using the Change Region verb in the OOC tab, as selecting a region closer to you may reduce latency.") /client/proc/is_connecting_from_localhost() var/static/list/localhost_addresses = list("127.0.0.1", "::1") @@ -1196,6 +1199,36 @@ popup.set_content(output) popup.open(FALSE) +/client/verb/change_region() + set category = "OOC" + set name = "Change Region" + + if(!length(GLOB.configuration.system.region_map)) + to_chat(usr, "Error: No extra regions defined for this server") + return + + var/list/target_regions = list("--DIRECT--") + for(var/region in GLOB.configuration.system.region_map) + target_regions += region + + var/formatted_existing = (prefs.server_region ? prefs.server_region : "--DIRECT--") + + var/choice = input(usr, "Select a region for routing optimisation.\nSelecting --DIRECT-- will bypass routing optimisations.", "Region", formatted_existing) as null|anything in target_regions + + if(!choice || (choice == formatted_existing)) + return + + prefs.server_region = choice + prefs.save_preferences(src) + + alert(usr, "Now routing you from [formatted_existing] to [choice]. You will briefly disconnect.", "ALERT", "Ok") + + if(choice == "--DIRECT--") + src << link("byond://[GLOB.configuration.url.server_url]") + else + src << link(GLOB.configuration.system.region_map[choice]) + + #undef LIMITER_SIZE #undef CURRENT_SECOND #undef SECOND_COUNT diff --git a/code/modules/client/login_processing/10-load_preferences.dm b/code/modules/client/login_processing/10-load_preferences.dm index 8794eac1b9c..8d6e506e34a 100644 --- a/code/modules/client/login_processing/10-load_preferences.dm +++ b/code/modules/client/login_processing/10-load_preferences.dm @@ -2,6 +2,8 @@ priority = 10 /datum/client_login_processor/load_preferences/get_query(client/C) + // If you ever need to remove a column from here, just replace the column name with NULL + // This saves you having to go around the entire codebase and fix columns var/datum/db_query/query = SSdbcore.NewQuery({"SELECT ooccolor, UI_style, @@ -24,7 +26,8 @@ screentip_color, ghost_darkness_level, colourblind_mode, - keybindings + keybindings, + server_region FROM player WHERE ckey=:ckey"}, list( "ckey" = C.ckey diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 94e84c318f9..b9fdb805cb2 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -123,6 +123,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts var/list/datum/keybindings = list() /// Keybinding overrides ("name" => ["key"...]) var/list/keybindings_overrides = null + /// Player's region override for routing optimisation + var/server_region = null /datum/preferences/New(client/C, datum/db_query/Q) // Process our query parent = C diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm index 63b035f4273..0e9c4a6eb40 100644 --- a/code/modules/client/preference/preferences_mysql.dm +++ b/code/modules/client/preference/preferences_mysql.dm @@ -26,6 +26,7 @@ ghost_darkness_level = query.item[20] colourblind_mode = query.item[21] keybindings = init_keybindings(raw = query.item[22]) + server_region = query.item[23] lastchangelog_2 = lastchangelog // Clone please @@ -48,6 +49,11 @@ screentip_color = sanitize_hexcolor(screentip_color, initial(screentip_color)) ghost_darkness_level = sanitize_integer(ghost_darkness_level, 0, 255, initial(ghost_darkness_level)) colourblind_mode = sanitize_inlist(colourblind_mode, list(COLOURBLIND_MODE_NONE, COLOURBLIND_MODE_DEUTER, COLOURBLIND_MODE_PROT, COLOURBLIND_MODE_TRIT), COLOURBLIND_MODE_NONE) + + // Sanitize the region + if(!(server_region in GLOB.configuration.system.region_map)) + server_region = null // This region doesnt exist anymore + return TRUE /datum/preferences/proc/save_preferences(client/C) @@ -82,7 +88,8 @@ screentip_color=:screentip_color, ghost_darkness_level=:ghost_darkness_level, colourblind_mode=:colourblind_mode, - keybindings=:keybindings + keybindings=:keybindings, + server_region=:server_region WHERE ckey=:ckey"}, list( // OH GOD THE PARAMETERS "ooccolour" = ooccolor, @@ -107,6 +114,7 @@ "colourblind_mode" = colourblind_mode, "keybindings" = json_encode(keybindings_overrides), "ckey" = C.ckey, + "server_region" = server_region, )) if(!query.warn_execute()) diff --git a/config/example/config.toml b/config/example/config.toml index a6d9da3c8de..3ee08a85cf4 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -747,6 +747,12 @@ external_tos_handler = false # Do not use in production. # Comment out to disable. #override_map = "/datum/map/test_tiny" +# Regional servers. +# This is not for separate DD instances per region, but if you have a geo-routing setup deployed to optimise routing for players +# I am 99.9% certain you will never need to fill this out +regional_servers = [ + #{name = "UK", ip = "byond://uk.paradisestation.org:6666"}, +] ################################################################