diff --git a/src/DMAPI/tgs/core/core.dm b/src/DMAPI/tgs/core/core.dm
index 674af2bf77..64226796d7 100644
--- a/src/DMAPI/tgs/core/core.dm
+++ b/src/DMAPI/tgs/core/core.dm
@@ -30,6 +30,8 @@
switch(version.minor)
if(0)
api_datum = /datum/tgs_api/v4
+ if(5)
+ api_datum = /datum/tgs_api/v5
var/datum/tgs_version/max_api_version = TgsMaximumAPIVersion();
if(version.suite != null && version.minor != null && version.patch != null && version.deprecated_patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter)
@@ -51,10 +53,10 @@
TGS_ERROR_LOG("Failed to activate API!")
/world/TgsMaximumAPIVersion()
- return new /datum/tgs_version("4.0.x.x")
+ return new /datum/tgs_version("5.x.x")
/world/TgsMinimumAPIVersion()
- return new /datum/tgs_version("3.2.0.0")
+ return new /datum/tgs_version("3.2.x")
/world/TgsInitializationComplete()
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
diff --git a/src/DMAPI/tgs/core/datum.dm b/src/DMAPI/tgs/core/datum.dm
index fb2508059a..3adecbb556 100644
--- a/src/DMAPI/tgs/core/datum.dm
+++ b/src/DMAPI/tgs/core/datum.dm
@@ -8,7 +8,7 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null)
src.version = version
/datum/tgs_api/latest
- parent_type = /datum/tgs_api/v4
+ parent_type = /datum/tgs_api/v5
TGS_PROTECT_DATUM(/datum/tgs_api)
diff --git a/src/DMAPI/tgs/includes.dm b/src/DMAPI/tgs/includes.dm
index 23fe376bf6..7723d9c2c8 100644
--- a/src/DMAPI/tgs/includes.dm
+++ b/src/DMAPI/tgs/includes.dm
@@ -2,11 +2,42 @@
#include "core\core.dm"
#include "core\datum.dm"
#include "core\tgs_version.dm"
+
#ifdef TGS_V3_API
#include "v3210\api.dm"
#include "v3210\commands.dm"
#endif
+
#include "v4\api.dm"
#include "v4\commands.dm"
+
#include "v5\api.dm"
#include "v5\commands.dm"
+#include "v5\undef.dm"
+
+/*
+The MIT License
+
+Copyright (c) 2017 Jordan Brown
+
+Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to
+deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
diff --git a/src/DMAPI/tgs/v5/_defines.dm b/src/DMAPI/tgs/v5/_defines.dm
index 2f060b3a76..f08e78c091 100644
--- a/src/DMAPI/tgs/v5/_defines.dm
+++ b/src/DMAPI/tgs/v5/_defines.dm
@@ -1,5 +1,6 @@
#define DMAPI5_PARAM_RUNTIME_INFORMATION_FILE "tgs_json"
-#define DMAPI5_TOPIC_DATA "data"
+#define DMAPI5_BRIDGE_DATA "data"
+#define DMAPI5_TOPIC_DATA "tgs_data"
#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0
#define DMAPI5_BRIDGE_COMMAND_VALIDATE 1
@@ -9,6 +10,7 @@
#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5
#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier"
+#define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage"
#define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType"
#define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort"
@@ -16,8 +18,7 @@
#define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage"
#define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel"
-#define DMAPI5_BRIDGE_RESPONSE_ERROR_MESSAGE "errorMessage"
-#define DMAPI5_BRIDGE_RESPONSE_ERROR_NEW_PORT "newPort"
+#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort"
#define DMAPI5_CHAT_MESSAGE_TEXT "text"
#define DMAPI5_CHAT_MESSAGE_CHANNEL_IDS "channelIds"
@@ -29,6 +30,9 @@
#define DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME "instanceName"
#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision"
#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges"
+#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel"
+#define DMAPI5_RUNTIME_INFORMATION_CHAT_COMMANDS_JSON "chatCommandsJson"
+#define DMAPI5_RUNTIME_INFORMATION_CHAT_CHANNELS_JSON "chatChannelsJson"
#define DMAPI5_TEST_MERGE_TIME_MERGED "timeMerged"
#define DMAPI5_TEST_MERGE_REVISION "revision"
@@ -36,6 +40,9 @@
#define DMAPI5_TEST_MERGE_BODY_AT_MERGE "bodyAtMerge"
#define DMAPI5_TEST_MERGE_URL "url"
#define DMAPI5_TEST_MERGE_AUTHOR "author"
+#define DMAPI5_TEST_MERGE_NUMBER "number"
+#define DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION "pullRequestRevision"
+#define DMAPI5_TEST_MERGE_COMMENT "comment"
#define DMAPI5_CHAT_COMMAND_NAME "name"
#define DMAPI5_CHAT_COMMAND_PARAMS "params"
@@ -57,7 +64,6 @@
#define DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE "newRebootState"
#define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName"
-#define DMAPI5_TOPIC_RESPONSE_ERROR_MESSAGE "errorMessage"
#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage"
#define DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES "chatResponses"
@@ -74,5 +80,35 @@
#define DMAPI5_CHAT_CHANNEL_CONNECTION_NAME "connectionName"
#define DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL "isAdminChannel"
#define DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL "isPrivateChannel"
-#define DMAPI5_CHAT_CHANNEL_IS_WATCHDOG_CHANNEL "isWatchdogChannel"
#define DMAPI5_CHAT_CHANNEL_TAG "tag"
+
+#define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name"
+#define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText"
+#define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly"
+
+/*
+The MIT License
+
+Copyright (c) 2020 Jordan Brown
+
+Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to
+deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
diff --git a/src/DMAPI/tgs/v5/api.dm b/src/DMAPI/tgs/v5/api.dm
index 96a037644a..9f8fb3abb8 100644
--- a/src/DMAPI/tgs/v5/api.dm
+++ b/src/DMAPI/tgs/v5/api.dm
@@ -1,30 +1,3 @@
-#define TGS4_PARAM_DEPLOYMENT_INFORMATION_FILE "tgs_json"
-#define TGS4_TOPIC_DATA "data"
-
-#define TGS4_INTEROP_ACCESS_IDENTIFIER "tgs_tok"
-
-#define TGS4_RESPONSE_SUCCESS "tgs_succ"
-
-#define TGS4_TOPIC_CHANGE_PORT "tgs_port"
-#define TGS4_TOPIC_CHANGE_REBOOT_MODE "tgs_rmode"
-#define TGS4_TOPIC_CHAT_COMMAND "tgs_chat_comm"
-#define TGS4_TOPIC_EVENT "tgs_event"
-#define TGS4_TOPIC_INTEROP_RESPONSE "tgs_interop"
-
-#define TGS4_COMM_NEW_PORT "tgs_new_port"
-#define TGS4_COMM_VALIDATE "tgs_validate"
-#define TGS4_COMM_SERVER_PRIMED "tgs_prime"
-#define TGS4_COMM_WORLD_REBOOT "tgs_reboot"
-#define TGS4_COMM_END_PROCESS "tgs_kill"
-#define TGS4_COMM_CHAT "tgs_chat_send"
-
-#define TGS4_PARAMETER_COMMAND "tgs_com"
-#define TGS4_PARAMETER_DATA "tgs_data"
-
-#define TGS4_PORT_CRITFAIL_MESSAGE " Must exit to let watchdog reboot..."
-
-#define EXPORT_TIMEOUT_DS 200
-
/datum/tgs_api/v5
var/access_identifier
var/instance_name
@@ -33,8 +6,7 @@
var/chat_commands_json_path
var/reboot_mode = TGS_REBOOT_MODE_NORMAL
var/security_level
-
- var/requesting_new_port = FALSE
+ var/server_port
var/list/intercepted_message_queue
@@ -47,13 +19,13 @@
var/export_lock = FALSE
-/datum/tgs_api/v4/ApiVersion()
+/datum/tgs_api/v5/ApiVersion()
return "5.0.0"
-/datum/tgs_api/v4/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level)
- json_path = world.params[TGS4_PARAM_INFO_JSON]
+/datum/tgs_api/v5/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level)
+ json_path = world.params[DMAPI5_PARAM_RUNTIME_INFORMATION_FILE]
if(!json_path)
- TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!")
+ TGS_ERROR_LOG("Missing [DMAPI5_PARAM_RUNTIME_INFORMATION_FILE] world parameter!")
return
var/json_file = file2text(json_path)
if(!json_file)
@@ -64,181 +36,176 @@
TGS_ERROR_LOG("Failed to decode info json: [json_file]")
return
- access_identifier = cached_json["accessIdentifier"]
- server_commands_json_path = cached_json["serverCommandsJson"]
+ access_identifier = cached_json[DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER]
+ server_port = cached_json[DMAPI5_RUNTIME_INFORMATION_SERVER_PORT]
- if(cached_json["apiValidateOnly"])
- TGS_INFO_LOG("Validating API and exiting...")
- Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]"))
+ if(cached_json[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY])
+ TGS_INFO_LOG("Validating DMAPI and exiting...")
+ Bridge(DMAPI5_BRIDGE_COMMAND_VALIDATE, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = Version()))
del(world)
- security_level = cached_json["securityLevel"]
- chat_channels_json_path = cached_json["chatChannelsJson"]
- chat_commands_json_path = cached_json["chatCommandsJson"]
+ security_level = cached_json[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL]
+ chat_channels_json_path = cached_json[DMAPI5_RUNTIME_INFORMATION_CHAT_CHANNELS_JSON]
+ chat_commands_json_path = cached_json[DMAPI5_RUNTIME_INFORMATION_CHAT_COMMANDS_JSON]
src.event_handler = event_handler
- instance_name = cached_json["instanceName"]
+ instance_name = cached_json[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME]
ListCustomCommands()
- var/list/revisionData = cached_json["revision"]
+ var/list/revisionData = cached_json[DMAPI5_RUNTIME_INFORMATION_REVISION]
if(revisionData)
cached_revision = new
- cached_revision.commit = revisionData["commitSha"]
- cached_revision.origin_commit = revisionData["originCommitSha"]
+ cached_revision.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA]
+ cached_revision.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA]
cached_test_merges = list()
- var/list/json = cached_json["testMerges"]
+ var/list/json = cached_json[DMAPI5_RUNTIME_INFORMATION_TEST_MERGES]
for(var/entry in json)
var/datum/tgs_revision_information/test_merge/tm = new
- tm.time_merged = text2num(entry["timeMerged"])
+ tm.time_merged = text2num(entry[DMAPI5_TEST_MERGE_TIME_MERGED])
- var/list/revInfo = entry["revision"]
+ var/list/revInfo = entry[DMAPI5_TEST_MERGE_REVISION]
if(revInfo)
- tm.commit = revInfo["commitSha"]
- tm.origin_commit = revInfo["originCommitSha"]
+ tm.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA]
+ tm.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA]
- tm.title = entry["titleAtMerge"]
- tm.body = entry["bodyAtMerge"]
- tm.url = entry["url"]
- tm.author = entry["author"]
- tm.number = entry["number"]
- tm.pull_request_commit = entry["pullRequestRevision"]
- tm.comment = entry["comment"]
+ tm.title = entry[DMAPI5_TEST_MERGE_TITLE_AT_MERGE]
+ tm.body = entry[DMAPI5_TEST_MERGE_BODY_AT_MERGE]
+ tm.url = entry[DMAPI5_TEST_MERGE_URL]
+ tm.author = entry[DMAPI5_TEST_MERGE_AUTHOR]
+ tm.number = entry[DMAPI5_TEST_MERGE_NUMBER]
+ tm.pull_request_commit = entry[DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION]
+ tm.comment = entry[DMAPI5_TEST_MERGE_COMMENT]
cached_test_merges += tm
return TRUE
-/datum/tgs_api/v4/OnInitializationComplete()
- Export(TGS4_COMM_SERVER_PRIMED)
+/datum/tgs_api/v5/OnInitializationComplete()
+ Bridge(TGS4_COMM_SERVER_PRIMED)
- var/tgs4_secret_sleep_offline_sauce = 24051994
+ var/tgs4_secret_sleep_offline_sauce = 29051994
var/old_sleep_offline = world.sleep_offline
world.sleep_offline = tgs4_secret_sleep_offline_sauce
sleep(1)
if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it
world.sleep_offline = old_sleep_offline
-/datum/tgs_api/v4/OnTopic(T)
+/datum/tgs_api/v5/TopicError(message)
+ return json_encode(list(DMAPI5_RESPONSE_ERROR_MESSAGE = message))
+
+/datum/tgs_api/v5/OnTopic(T)
var/list/params = params2list(T)
- var/their_sCK = params[TGS4_INTEROP_ACCESS_IDENTIFIER]
- if(!their_sCK)
+ var/json = params[DMAPI5_TOPIC_DATA]
+ if(!json)
return FALSE //continue world/Topic
+ var/list/topic_parameters = json_decode(json)
+ if(!topic_parameters)
+ return TopicError("Invalid topic parameters json!");
+
+ var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER]
if(their_sCK != access_identifier)
- return "Invalid comms key!";
+ return TopicError("Invalid access identifier!");
- var/command = params[TGS4_PARAMETER_COMMAND]
- if(!command)
- return "No command!"
-
- . = TGS4_RESPONSE_SUCCESS
+ var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE]
+ if(command == null)
+ return TopicError("No command type!")
switch(command)
- if(TGS4_TOPIC_CHAT_COMMAND)
- var/result = HandleCustomCommand(params[TGS4_PARAMETER_DATA])
- if(result == null)
- result = "Error running chat command!"
+ if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND)
+ var/result = HandleCustomCommand(topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND])
+ if(!result)
+ result = TopicError("Error running chat command!")
return result
- if(TGS4_TOPIC_EVENT)
+ if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION)
intercepted_message_queue = list()
- var/list/event_notification = json_decode(params[TGS4_PARAMETER_DATA])
- var/list/event_parameters = event_notification["Parameters"]
-
- var/list/event_call = list(event_notification["Type"])
+ var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]
+ var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS]
+ var/list/event_call = list(event_notification[DMAPI5_EVENT_NOTIFICATION_TYPE])
if(event_parameters)
event_call += event_parameters
if(event_handler != null)
event_handler.HandleEvent(arglist(event_call))
- . = json_encode(intercepted_message_queue)
+ var/list/response = list()
+ if(intercepted_message_queue.len)
+ response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue
intercepted_message_queue = null
- return
- if(TGS4_TOPIC_INTEROP_RESPONSE)
- last_interop_response = json_decode(params[TGS4_PARAMETER_DATA])
- return
- if(TGS4_TOPIC_CHANGE_PORT)
- var/new_port = text2num(params[TGS4_PARAMETER_DATA])
+ return json_encode(response)
+ if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT)
+ var/new_port = text2num(topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT])
if (!(new_port > 0))
- return "Invalid port: [new_port]"
+ return TopicError("Invalid port: [new_port]")
//the topic still completes, miraculously
//I honestly didn't believe byond could do it
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port)
if(!world.OpenPort(new_port))
- return "Port change failed!"
- return
- if(TGS4_TOPIC_CHANGE_REBOOT_MODE)
- var/new_reboot_mode = text2num(params[TGS4_PARAMETER_DATA])
+ return TopicError("Port change failed!")
+ return json_encode(list())
+ if(DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE)
+ var/new_reboot_mode = text2num(topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE])
if(event_handler != null)
event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode)
reboot_mode = new_reboot_mode
- return
+ return json_encode(list())
+ if(DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED)
+ var/new_instance_name = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]
+ if(!new_instance_name)
+ return TopicError("Missing new instance name!")
+ instance_name = new_instance_name
+ return json_encode(list())
- return "Unknown command: [command]"
+ return TopicError("Unknown command: [command]")
+
+/datum/tgs_api/v5/proc/Bridge(command, list/data)
+ if(command == null)
+ TGS_ERROR_LOG("Attempted to bridge with no command!")
+ return
-/datum/tgs_api/v4/proc/Export(command, list/data, override_requesting_new_port = FALSE)
if(!data)
data = list()
- data[TGS4_PARAMETER_COMMAND] = command
+
+ data[DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE] = command
+ data[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] = access_identifier
+
var/json = json_encode(data)
+ var/encoded_json = url_encode(json)
+
+ // This is an infinite sleep until we get a response
+ var/export_response = world.Export("http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]")
+ if(!export_response)
+ TGS_ERROR_LOG("Failed export request: [json]")
+ return
+
+ var/response_json = file2text(export_result["CONTENT"])
+ if(!response_json)
+ TGS_ERROR_LOG("Failed export request, missing content!")
+ return
+
+ var/list/bridge_response = json_decode(response_json)
+ if(!bridge_response)
+ TGS_ERROR_LOG("Failed export request, bad json: [response_json]")
+ return
- while(requesting_new_port && !override_requesting_new_port)
- sleep(1)
+ var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE]
+ if(error)
+ TGS_ERROR_LOG("Failed export request, bad request: [error]")
+ return
+
+ return bridge_response
- //we need some port open at this point to facilitate return communication
- if(!world.port)
- requesting_new_port = TRUE
- if(!world.OpenPort(0)) //open any port
- TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
-
- //request a new port
- export_lock = FALSE
- var/list/new_port_json = Export(TGS4_COMM_NEW_PORT, list(TGS4_PARAMETER_DATA = "[world.port]"), TRUE) //stringify this on purpose
-
- if(!new_port_json)
- TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
-
- var/new_port = new_port_json[TGS4_PARAMETER_DATA]
- if(!isnum(new_port) || new_port <= 0)
- TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
-
- if(new_port != world.port && !world.OpenPort(new_port))
- TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
- requesting_new_port = FALSE
-
- while(export_lock)
- sleep(1)
- export_lock = TRUE
-
- last_interop_response = null
- fdel(server_commands_json_path)
- text2file(json, server_commands_json_path)
-
- for(var/I = 0; I < EXPORT_TIMEOUT_DS && !last_interop_response; ++I)
- sleep(1)
-
- if(!last_interop_response)
- TGS_ERROR_LOG("Failed to get export result for: [json]")
- else
- . = last_interop_response
-
- export_lock = FALSE
-
-/datum/tgs_api/v4/OnReboot()
- var/list/result = Export(TGS4_COMM_WORLD_REBOOT)
+/datum/tgs_api/v5/OnReboot()
+ var/list/result = Bridge(DMAPI5_BRIDGE_COMMAND_REBOOT)
if(!result)
return
//okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter
- var/port = result[TGS4_PARAMETER_DATA]
+ var/port = result[DMAPI5_BRIDGE_RESPONSE_NEW_PORT]
if(!isnum(port))
return //this is valid, server may just want use to reboot
@@ -249,74 +216,74 @@
if(!world.OpenPort(port))
TGS_ERROR_LOG("Unable to set port to [port]!")
-/datum/tgs_api/v4/InstanceName()
+/datum/tgs_api/v5/InstanceName()
return instance_name
-/datum/tgs_api/v4/TestMerges()
+/datum/tgs_api/v5/TestMerges()
return cached_test_merges
-/datum/tgs_api/v4/EndProcess()
- Export(TGS4_COMM_END_PROCESS)
+/datum/tgs_api/v5/EndProcess()
+ Bridge(DMAPI5_BRIDGE_COMMAND_KILL)
-/datum/tgs_api/v4/Revision()
+/datum/tgs_api/v5/Revision()
return cached_revision
-/datum/tgs_api/v4/ChatBroadcast(message, list/channels)
+/datum/tgs_api/v5/ChatBroadcast(message, list/channels)
var/list/ids
if(length(channels))
ids = list()
for(var/I in channels)
var/datum/tgs_chat_channel/channel = I
ids += channel.id
- message = list("message" = message, "channelIds" = ids)
+ message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = ids)
if(intercepted_message_queue)
intercepted_message_queue += list(message)
else
- Export(TGS4_COMM_CHAT, message)
+ Bridge(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE, message)
-/datum/tgs_api/v4/ChatTargetedBroadcast(message, admin_only)
+/datum/tgs_api/v5/ChatTargetedBroadcast(message, admin_only)
var/list/channels = list()
for(var/I in ChatChannelInfo())
var/datum/tgs_chat_channel/channel = I
if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only)))
channels += channel.id
- message = list("message" = message, "channelIds" = channels)
+ message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = channels)
if(intercepted_message_queue)
intercepted_message_queue += list(message)
else
Export(TGS4_COMM_CHAT, message)
-/datum/tgs_api/v4/ChatPrivateMessage(message, datum/tgs_chat_user/user)
- message = list("message" = message, "channelIds" = list(user.channel.id))
+/datum/tgs_api/v5/ChatPrivateMessage(message, datum/tgs_chat_user/user)
+ message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = list(user.channel.id))
if(intercepted_message_queue)
intercepted_message_queue += list(message)
else
Export(TGS4_COMM_CHAT, message)
-/datum/tgs_api/v4/ChatChannelInfo()
+/datum/tgs_api/v5/ChatChannelInfo()
. = list()
//no caching cause tgs may change this
var/list/json = json_decode(file2text(chat_channels_json_path))
for(var/I in json)
. += DecodeChannel(I)
-/datum/tgs_api/v4/proc/DecodeChannel(channel_json)
+/datum/tgs_api/v5/proc/DecodeChannel(channel_json)
var/datum/tgs_chat_channel/channel = new
- channel.id = channel_json["id"]
- channel.friendly_name = channel_json["friendlyName"]
- channel.connection_name = channel_json["connectionName"]
- channel.is_admin_channel = channel_json["isAdminChannel"]
- channel.is_private_channel = channel_json["isPrivateChannel"]
- channel.custom_tag = channel_json["tag"]
+ channel.id = channel_json[DMAPI5_CHAT_CHANNEL_ID]
+ channel.friendly_name = channel_json[DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME]
+ channel.connection_name = channel_json[DMAPI5_CHAT_CHANNEL_CONNECTION_NAME]
+ channel.is_admin_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL]
+ channel.is_private_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL]
+ channel.custom_tag = channel_json[DMAPI5_CHAT_CHANNEL_TAG]
return channel
-/datum/tgs_api/v4/SecurityLevel()
+/datum/tgs_api/v5/SecurityLevel()
return security_level
/*
The MIT License
-Copyright (c) 2017 Jordan Brown
+Copyright (c) 2020 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/src/DMAPI/tgs/v5/commands.dm b/src/DMAPI/tgs/v5/commands.dm
index 1d9951bc04..a3f27f99af 100644
--- a/src/DMAPI/tgs/v5/commands.dm
+++ b/src/DMAPI/tgs/v5/commands.dm
@@ -1,4 +1,4 @@
-/datum/tgs_api/v4/proc/ListCustomCommands()
+/datum/tgs_api/v5/proc/ListCustomCommands()
var/results = list()
custom_commands = list()
for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command)
@@ -12,7 +12,7 @@
var/datum/other = custom_commands[command_name]
TGS_ERROR_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!")
continue
- results += list(list("name" = command_name, "help_text" = stc.help_text, "admin_only" = stc.admin_only))
+ results += list(list(DMAPI5_CUSTOM_CHAT_COMMAND_NAME = command_name, DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT = stc.help_text, DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY = stc.admin_only))
custom_commands[command_name] = stc
var/commands_file = chat_commands_json_path
@@ -20,31 +20,31 @@
return
text2file(json_encode(results), commands_file)
-/datum/tgs_api/v4/proc/HandleCustomCommand(command_json)
- var/list/data = json_decode(command_json)
- var/command = data["command"]
- var/user = data["user"]
- var/params = data["params"]
+/datum/tgs_api/v5/proc/HandleCustomCommand(list/command_json)
+ var/command = data[DMAPI5_CHAT_COMMAND_NAME]
+ var/user = data[DMAPI5_CHAT_COMMAND_USER]
+ var/params = data[DMAPI5_CHAT_COMMAND_PARAMS]
var/datum/tgs_chat_user/u = new
- u.id = user["id"]
- u.friendly_name = user["friendlyName"]
- u.mention = user["mention"]
- u.channel = DecodeChannel(user["channel"])
+ u.id = user[DMAPI5_CHAT_USER_ID]
+ u.friendly_name = user[DMAPI5_CHAT_USER_FRIENDLY_NAME]
+ u.mention = user[DMAPI5_CHAT_USER_MENTION]
+ u.channel = DecodeChannel(user[DMAPI5_CHAT_USER_CHANNEL])
var/datum/tgs_chat_command/sc = custom_commands[command]
if(sc)
- var/result = sc.Run(u, params)
- if(result == null)
- result = ""
- return result
- return "Unknown command: [command]!"
+ var/textResponse = sc.Run(u, params)
+ var/list/topic_response = list()
+ if(textResponse != null)
+ topic_response(DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE = textResponse)
+ return topic_response
+ return TopicError("Unknown custom chat command: [command]!")
/*
The MIT License
-Copyright (c) 2017 Jordan Brown
+Copyright (c) 2020 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/src/DMAPI/tgs/v5/undef.dm b/src/DMAPI/tgs/v5/undef.dm
new file mode 100644
index 0000000000..a16ad00e38
--- /dev/null
+++ b/src/DMAPI/tgs/v5/undef.dm
@@ -0,0 +1,114 @@
+#undef DMAPI5_PARAM_RUNTIME_INFORMATION_FILE
+#undef DMAPI5_BRIDGE_DATA
+#undef DMAPI5_TOPIC_DATA
+
+#undef DMAPI5_BRIDGE_COMMAND_PORT_UPDATE
+#undef DMAPI5_BRIDGE_COMMAND_VALIDATE
+#undef DMAPI5_BRIDGE_COMMAND_PRIME
+#undef DMAPI5_BRIDGE_COMMAND_REBOOT
+#undef DMAPI5_BRIDGE_COMMAND_KILL
+#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND
+
+#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER
+#undef DMAPI5_RESPONSE_ERROR_MESSAGE
+
+#undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE
+#undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT
+#undef DMAPI5_BRIDGE_PARAMETER_VERSION
+#undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE
+#undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL
+
+#undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT
+
+#undef DMAPI5_CHAT_MESSAGE_TEXT
+#undef DMAPI5_CHAT_MESSAGE_CHANNEL_IDS
+
+#undef DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER
+#undef DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION
+#undef DMAPI5_RUNTIME_INFORMATION_SERVER_PORT
+#undef DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY
+#undef DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME
+#undef DMAPI5_RUNTIME_INFORMATION_REVISION
+#undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES
+#undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL
+#undef DMAPI5_RUNTIME_INFORMATION_CHAT_COMMANDS_JSON
+#undef DMAPI5_RUNTIME_INFORMATION_CHAT_CHANNELS_JSON
+
+#undef DMAPI5_TEST_MERGE_TIME_MERGED
+#undef DMAPI5_TEST_MERGE_REVISION
+#undef DMAPI5_TEST_MERGE_TITLE_AT_MERGE
+#undef DMAPI5_TEST_MERGE_BODY_AT_MERGE
+#undef DMAPI5_TEST_MERGE_URL
+#undef DMAPI5_TEST_MERGE_AUTHOR
+#undef DMAPI5_TEST_MERGE_NUMBER
+#undef DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION
+#undef DMAPI5_TEST_MERGE_COMMENT
+
+#undef DMAPI5_CHAT_COMMAND_NAME
+#undef DMAPI5_CHAT_COMMAND_PARAMS
+#undef DMAPI5_CHAT_COMMAND_USER
+
+#undef DMAPI5_EVENT_NOTIFICATION_TYPE
+#undef DMAPI5_EVENT_NOTIFICATION_PARAMETERS
+
+#undef DMAPI5_TOPIC_COMMAND_CHAT_COMMAND
+#undef DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION
+#undef DMAPI5_TOPIC_COMMAND_CHANGE_PORT
+#undef DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE
+#undef DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED
+
+#undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE
+#undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND
+#undef DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION
+#undef DMAPI5_TOPIC_PARAMETER_NEW_PORT
+#undef DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE
+#undef DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME
+
+#undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE
+#undef DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES
+
+#undef DMAPI5_REVISION_INFORMATION_COMMIT_SHA
+#undef DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA
+
+#undef DMAPI5_CHAT_USER_ID
+#undef DMAPI5_CHAT_USER_FRIENDLY_NAME
+#undef DMAPI5_CHAT_USER_MENTION
+#undef DMAPI5_CHAT_USER_CHANNEL
+
+#undef DMAPI5_CHAT_CHANNEL_ID
+#undef DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME
+#undef DMAPI5_CHAT_CHANNEL_CONNECTION_NAME
+#undef DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL
+#undef DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL
+#undef DMAPI5_CHAT_CHANNEL_TAG
+
+#undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME
+#undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT
+#undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY
+
+/*
+The MIT License
+
+Copyright (c) 2020 Jordan Brown
+
+Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to
+deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
diff --git a/src/Tgstation.Server.Host/Components/Interop/Bridge/BridgeResponse.cs b/src/Tgstation.Server.Host/Components/Interop/Bridge/BridgeResponse.cs
index 76801de132..82be2b15f5 100644
--- a/src/Tgstation.Server.Host/Components/Interop/Bridge/BridgeResponse.cs
+++ b/src/Tgstation.Server.Host/Components/Interop/Bridge/BridgeResponse.cs
@@ -6,7 +6,7 @@
public sealed class BridgeResponse : DMApiResponse
{
///
- /// The new port for requests.
+ /// The new port for requests.
///
public ushort? NewPort { get; set; }
}
diff --git a/src/Tgstation.Server.Host/Components/Interop/DMApiConstants.cs b/src/Tgstation.Server.Host/Components/Interop/DMApiConstants.cs
index 8a4e69bfb0..339f6984ab 100644
--- a/src/Tgstation.Server.Host/Components/Interop/DMApiConstants.cs
+++ b/src/Tgstation.Server.Host/Components/Interop/DMApiConstants.cs
@@ -23,7 +23,7 @@ namespace Tgstation.Server.Host.Components.Interop
///
/// Parameter json is encoded in for topic requests.
///
- public const string TopicData = "data";
+ public const string TopicData = "tgs_data";
///
/// The DMAPI being used.
diff --git a/tests/DMAPI/Test.dm b/tests/DMAPI/Test.dm
index addf8c7603..cefcbe33ff 100644
--- a/tests/DMAPI/Test.dm
+++ b/tests/DMAPI/Test.dm
@@ -22,3 +22,10 @@ var/list/clients = list()
/client/Del()
clients -= src
return ..()
+
+/datum/tgs_chat_command/echo
+ name = "echo"
+ help_text = "echos input parameters"
+
+/datum/tgs_chat_command/echo/Run(datum/tgs_chat_user/sender, params)
+ return "[sender.channel.connection_name]|[sender.channel.friendly_name]|[sender.friendly_name]: [params]"