From 8a21fc2e6c976d928bf64b9b68d5439d62c3931a Mon Sep 17 00:00:00 2001 From: Leshana Date: Sun, 24 May 2020 02:10:54 -0400 Subject: [PATCH] Add code to enable communication with VGS VGS provides a subset of TGS functionality, mostly just the discord bot. It extends TGS datums and adds a little bit. Right now its done in parallel to TGS's code to minimize impact of not having the rest of DMAPI v5 impemented. --- code/__defines/tgs.config.dm | 1 - code/__defines/tgs.dm | 1 + code/controllers/configuration.dm | 10 ++++ code/game/world.dm | 2 + code/modules/client/client procs.dm | 1 + code/modules/tgs/includes.dm | 1 + code/modules/tgs/v5/_defines.dm | 3 ++ code/modules/tgs/v5/api.dm | 5 ++ code/modules/tgs/v5/api_vgs.dm | 76 +++++++++++++++++++++++++++++ 9 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 code/modules/tgs/v5/api_vgs.dm diff --git a/code/__defines/tgs.config.dm b/code/__defines/tgs.config.dm index 1ae65934198..c02ed92daaf 100644 --- a/code/__defines/tgs.config.dm +++ b/code/__defines/tgs.config.dm @@ -1,5 +1,4 @@ #define TGS_EXTERNAL_CONFIGURATION -#define TGS_V3_API #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name) #define TGS_READ_GLOBAL(Name) GLOB.##Name #define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value diff --git a/code/__defines/tgs.dm b/code/__defines/tgs.dm index e164a4ec96a..e3ae002c588 100644 --- a/code/__defines/tgs.dm +++ b/code/__defines/tgs.dm @@ -104,6 +104,7 @@ //Put this at the start of /world/Topic() #define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return +#define VGS_TOPIC var/vgs_topic_return = VgsTopic(args[1]); if(vgs_topic_return) return vgs_topic_return // VOREStation Edit - VGS //Call this at the beginning of world/Reboot(reason) /world/proc/TgsReboot() diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 8a3b7c560b5..98a3f817a3f 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -276,6 +276,9 @@ var/list/gamemode_cache = list() // whether or not to use the nightshift subsystem to perform lighting changes var/static/enable_night_shifts = FALSE + + var/static/vgs_access_identifier = null // VOREStation Edit - VGS + var/static/vgs_server_port = null // VOREStation Edit - VGS /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode @@ -906,6 +909,13 @@ var/list/gamemode_cache = list() if("enable_night_shifts") config.enable_night_shifts = TRUE + + // VOREStation Edit Start - Can't be in _vr file because it is loaded too late. + if("vgs_access_identifier") + config.vgs_access_identifier = value + if("vgs_server_port") + config.vgs_server_port = text2num(value) + // VOREStation Edit End else log_misc("Unknown setting in configuration: '[name]'") diff --git a/code/game/world.dm b/code/game/world.dm index 8d0f5cd02c3..7fefc25cca9 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -16,6 +16,7 @@ to_world_log("Your server's byond version does not meet the recommended requirements for this server. Please update BYOND") TgsNew() + VgsNew() // VOREStation Edit - VGS config.post_load() @@ -85,6 +86,7 @@ var/world_topic_spam_protect_time = world.timeofday /world/Topic(T, addr, master, key) TGS_TOPIC + VGS_TOPIC // VOREStation Edit - VGS log_topic("\"[T]\", from:[addr], master:[master], key:[key]") if (T == "ping") diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 8c14493820b..1fae4dec3e3 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -95,6 +95,7 @@ log_and_message_admins("[ckey] has registered their Discord ID to obtain the Crew Member role. Their Discord snowflake ID is: [their_id]") admin_chat_message(message = "[ckey] has registered their Discord ID to obtain the Crew Member role. Their Discord is: <@[their_id]>", color = "#4eff22") notes_add(ckey, "Discord ID: [their_id]") + world.VgsAddMemberRole(their_id) else to_chat(src, "There was an error registering your Discord ID in the database. Contact an administrator.") log_and_message_admins("[ckey] failed to register their Discord ID. Their Discord snowflake ID is: [their_id]. Is the database connected?") diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm index 764adbc3a93..b9ef0f21ebb 100644 --- a/code/modules/tgs/includes.dm +++ b/code/modules/tgs/includes.dm @@ -13,6 +13,7 @@ #include "v5\_defines.dm" #include "v5\api.dm" +#include "v5\api_vgs.dm" // VOREStation Edit - Include here so it has access to v5 defines #include "v5\commands.dm" #include "v5\chat_commands.dm" #include "v5\undef.dm" diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm index 2baf3e12d72..ce6f4b109d9 100644 --- a/code/modules/tgs/v5/_defines.dm +++ b/code/modules/tgs/v5/_defines.dm @@ -10,6 +10,7 @@ #define DMAPI5_BRIDGE_COMMAND_REBOOT 3 #define DMAPI5_BRIDGE_COMMAND_KILL 4 #define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5 +#define DMAPI5_BRIDGE_COMMAND_ADD_MEMBER_ROLE 6 // VOREStation Edit #define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier" #define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage" @@ -20,6 +21,7 @@ #define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage" #define DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS "customCommands" #define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel" +#define DMAPI5_BRIDGE_PARAMETER_CHAT_USER_ID "chatUserId" // VOREStation Edit #define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort" #define DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION "runtimeInformation" @@ -64,6 +66,7 @@ #define DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE 6 #define DMAPI5_TOPIC_COMMAND_HEARTBEAT 7 #define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8 +#define DMAPI5_TOPIC_COMMAND_GET_CHAT_COMMANDS 9 // VOREStation Edit #define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType" #define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand" diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm index eedefb28770..d0d6f2d0811 100644 --- a/code/modules/tgs/v5/api.dm +++ b/code/modules/tgs/v5/api.dm @@ -125,6 +125,11 @@ if(!result) result = TopicResponse("Error running chat command!") return result + // VOREStation Edit Start - GetChatCommands command + if(DMAPI5_TOPIC_COMMAND_GET_CHAT_COMMANDS) + var/topic_response = list(DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands()) + return json_encode(topic_response) + // VOREStation Edit - End if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION) intercepted_message_queue = list() var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION] diff --git a/code/modules/tgs/v5/api_vgs.dm b/code/modules/tgs/v5/api_vgs.dm new file mode 100644 index 00000000000..aa43a1655f0 --- /dev/null +++ b/code/modules/tgs/v5/api_vgs.dm @@ -0,0 +1,76 @@ +// We currently isolate ourselves in a different variable so that only the specific APIs we choose will be active. +// Eventually it would be good to handle all the TGS Apis properly and we can use the same. +GLOBAL_DATUM(vgs, /datum/tgs_api) + +// Supply our own New functionality so we can read from config instead of world params +/world/proc/VgsNew(datum/tgs_event_handler/event_handler) + var/current_api = GLOB.vgs + if(current_api) + TGS_ERROR_LOG("API datum already set (\ref[current_api] ([current_api]))! Was TgsNew() called more than once?") + return + + // If we don't have a configured access identifier we aren't meant to use VGS + if(!config.vgs_access_identifier) + TGS_INFO_LOG("Skipping VGS: No access identifier configured") + return + + var/datum/tgs_api/api_datum = /datum/tgs_api/v5/vgs1 + TGS_INFO_LOG("Activating API for version [api_datum]") + + if(event_handler && !istype(event_handler)) + TGS_ERROR_LOG("Invalid parameter for event_handler: [event_handler]") + event_handler = null + + var/datum/tgs_api/new_api = new api_datum(event_handler) + GLOB.vgs = new_api + + var/result = new_api.OnWorldNew() + if(!result || result == TGS_UNIMPLEMENTED) + GLOB.vgs = null + TGS_ERROR_LOG("Failed to activate API!") + +/world/proc/VgsTopic(T) + var/datum/tgs_api/api = GLOB.vgs + if(api) + var/result = api.OnTopic(T) + if(result != TGS_UNIMPLEMENTED) + return result + +/world/proc/VgsAddMemberRole(chat_user_id) + var/datum/tgs_api/v5/vgs1/api = GLOB.vgs + if(api) + api.AddMemberRole(chat_user_id) + +/datum/tgs_api/v5/vgs1 + server_port = 8080 // Default port + +// Override to prevent error messages from the lack of revision/test_merge information, and to use config isntead of params. +/datum/tgs_api/v5/vgs1/OnWorldNew() + if(config.vgs_server_port) + server_port = config.vgs_server_port + access_identifier = config.vgs_access_identifier + + var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) + if(!istype(bridge_response)) + TGS_ERROR_LOG("Failed initial bridge request!") + return FALSE + + var/list/runtime_information = bridge_response[DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION] + if(!istype(runtime_information)) + TGS_ERROR_LOG("Failed to decode runtime information from bridge response: [json_encode(bridge_response)]!") + return FALSE + + version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION]) + instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME] + + chat_channels = list() + DecodeChannels(runtime_information) + + return TRUE + +/datum/tgs_api/v5/vgs1/proc/AddMemberRole(chat_user_id) + Bridge(DMAPI5_BRIDGE_COMMAND_ADD_MEMBER_ROLE, list(DMAPI5_BRIDGE_PARAMETER_CHAT_USER_ID = chat_user_id)) + +// /datum/tgs_api/v5/vgs1/RequireInitialBridgeResponse() +// while(!instance_name) +// sleep(1)