Skip to content

Commit

Permalink
Update TGS DMAPI
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Jan 18, 2025
1 parent e775e7b commit a2651a5
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 101 deletions.
187 changes: 153 additions & 34 deletions code/__DEFINES/tgs.dm

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion code/modules/tgs/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2017-2023 Jordan Brown
Copyright (c) 2017-2024 Jordan Brown

Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
Expand Down
2 changes: 1 addition & 1 deletion code/modules/tgs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DMAPI Internals

This folder should be placed on it's own inside a codebase that wishes to use the TGS DMAPI. Warranty void if modified.
This folder should be placed on its own inside a codebase that wishes to use the TGS DMAPI. Warranty void if modified.

- [includes.dm](./includes.dm) is the file that should be included by DM code, it handles including the rest.
- The [core](./core) folder includes all code not directly part of any API version.
Expand Down
2 changes: 1 addition & 1 deletion code/modules/tgs/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This folder contains all DMAPI code not directly involved in an API.

- [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals.
- [byond_world_export.dm](./byond_world_export.dm) contains the default `/datum/tgs_http_handler` implementation which uses `world.Export()`.
- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code.
- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement.
- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition
-
22 changes: 22 additions & 0 deletions code/modules/tgs/core/byond_world_export.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/datum/tgs_http_handler/byond_world_export

/datum/tgs_http_handler/byond_world_export/PerformGet(url)
// This is an infinite sleep until we get a response
var/export_response = world.Export(url)
TGS_DEBUG_LOG("byond_world_export: Export complete")

if(!export_response)
TGS_ERROR_LOG("byond_world_export: Failed request: [url]")
return new /datum/tgs_http_result(null, FALSE)

var/content = export_response["CONTENT"]
if(!content)
TGS_ERROR_LOG("byond_world_export: Failed request, missing content!")
return new /datum/tgs_http_result(null, FALSE)

var/response_json = TGS_FILE2TEXT_NATIVE(content)
if(!response_json)
TGS_ERROR_LOG("byond_world_export: Failed request, failed to load content!")
return new /datum/tgs_http_result(null, FALSE)

return new /datum/tgs_http_result(response_json, TRUE)
33 changes: 28 additions & 5 deletions code/modules/tgs/core/core.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE, datum/tgs_http_handler/http_handler = null)
var/current_api = TGS_READ_GLOBAL(tgs)
if(current_api)
TGS_ERROR_LOG("API datum already set (\ref[current_api] ([current_api]))! Was TgsNew() called more than once?")
Expand Down Expand Up @@ -42,11 +42,11 @@

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)
TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.")
TGS_ERROR_LOG("Detected unknown Interop API version! Defaulting to latest. Update the DMAPI to fix this problem.")
api_datum = /datum/tgs_api/latest

if(!api_datum)
TGS_ERROR_LOG("Found unsupported API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.")
TGS_ERROR_LOG("Found unsupported Interop API version: [raw_parameter]. If this is a valid version please report this, backporting is done on demand.")
return

TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]")
Expand All @@ -55,7 +55,10 @@
TGS_ERROR_LOG("Invalid parameter for event_handler: [event_handler]")
event_handler = null

var/datum/tgs_api/new_api = new api_datum(event_handler, version)
if(!http_handler)
http_handler = new /datum/tgs_http_handler/byond_world_export

var/datum/tgs_api/new_api = new api_datum(event_handler, version, http_handler)

TGS_WRITE_GLOBAL(tgs, new_api)

Expand Down Expand Up @@ -107,6 +110,13 @@
if(api)
return api.ApiVersion()

/world/TgsEngine()
#ifdef OPENDREAM
return TGS_ENGINE_TYPE_OPENDREAM
#else
return TGS_ENGINE_TYPE_BYOND
#endif

/world/TgsInstanceName()
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
Expand Down Expand Up @@ -153,4 +163,17 @@
/world/TgsSecurityLevel()
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
api.SecurityLevel()
return api.SecurityLevel()

/world/TgsVisibility()
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
return api.Visibility()

/world/TgsTriggerEvent(event_name, list/parameters, wait_for_completion = FALSE)
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
if(!istype(parameters, /list))
parameters = list()

return api.TriggerEvent(event_name, parameters, wait_for_completion)
19 changes: 17 additions & 2 deletions code/modules/tgs/core/datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null)

var/list/warned_deprecated_command_runs

/datum/tgs_api/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version)
. = ..()
/datum/tgs_api/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version, datum/tgs_http_handler/http_handler)
..()
src.event_handler = event_handler
src.version = version

/datum/tgs_api/proc/TerminateWorld()
while(TRUE)
TGS_DEBUG_LOG("About to terminate world. Tick: [world.time], sleep_offline: [world.sleep_offline]")
world.sleep_offline = FALSE // https://www.byond.com/forum/post/2894866
del(world)
world.sleep_offline = FALSE // just in case, this is BYOND after all...
sleep(world.tick_lag)
TGS_DEBUG_LOG("BYOND DIDN'T TERMINATE THE WORLD!!! TICK IS: [world.time], sleep_offline: [world.sleep_offline]")

/datum/tgs_api/latest
parent_type = /datum/tgs_api/v5

Expand Down Expand Up @@ -57,3 +66,9 @@ TGS_PROTECT_DATUM(/datum/tgs_api)

/datum/tgs_api/proc/SecurityLevel()
return TGS_UNIMPLEMENTED

/datum/tgs_api/proc/Visibility()
return TGS_UNIMPLEMENTED

/datum/tgs_api/proc/TriggerEvent(event_name, list/parameters, wait_for_completion)
return FALSE
1 change: 1 addition & 0 deletions code/modules/tgs/core/tgs_version.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/datum/tgs_version/New(raw_parameter)
..()
src.raw_parameter = raw_parameter
deprefixed_parameter = replacetext(raw_parameter, "/tg/station 13 Server v", "")
var/list/version_bits = splittext(deprefixed_parameter, ".")
Expand Down
1 change: 1 addition & 0 deletions code/modules/tgs/includes.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "core\_definitions.dm"
#include "core\byond_world_export.dm"
#include "core\core.dm"
#include "core\datum.dm"
#include "core\tgs_version.dm"
Expand Down
16 changes: 8 additions & 8 deletions code/modules/tgs/v4/api.dm
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
if(cached_json["apiValidateOnly"])
TGS_INFO_LOG("Validating API and exiting...")
Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]"))
del(world)
TerminateWorld()

security_level = cached_json["securityLevel"]
chat_channels_json_path = cached_json["chatChannelsJson"]
Expand Down Expand Up @@ -181,43 +181,43 @@
var/json = json_encode(data)

while(requesting_new_port && !override_requesting_new_port)
sleep(1)
sleep(world.tick_lag)

//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)
TerminateWorld()

//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)
TerminateWorld()

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)
TerminateWorld()

if(new_port != world.port && !world.OpenPort(new_port))
TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]")
del(world)
TerminateWorld()
requesting_new_port = FALSE

while(export_lock)
sleep(1)
sleep(world.tick_lag)
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)
sleep(world.tick_lag)

if(!last_interop_response)
TGS_ERROR_LOG("Failed to get export result for: [json]")
Expand Down
2 changes: 1 addition & 1 deletion code/modules/tgs/v5/__interop_version.dm
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"5.6.1"
"5.10.0"
15 changes: 14 additions & 1 deletion code/modules/tgs/v5/_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
#define DMAPI5_TOPIC_REQUEST_LIMIT 65528
#define DMAPI5_TOPIC_RESPONSE_LIMIT 65529

#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0
#define DMAPI5_BRIDGE_COMMAND_STARTUP 1
#define DMAPI5_BRIDGE_COMMAND_PRIME 2
#define DMAPI5_BRIDGE_COMMAND_REBOOT 3
#define DMAPI5_BRIDGE_COMMAND_KILL 4
#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5
#define DMAPI5_BRIDGE_COMMAND_CHUNK 6
#define DMAPI5_BRIDGE_COMMAND_EVENT 7

#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier"
#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands"
#define DMAPI5_PARAMETER_TOPIC_PORT "topicPort"

#define DMAPI5_CHUNK "chunk"
#define DMAPI5_CHUNK_PAYLOAD "payload"
Expand All @@ -34,6 +35,7 @@
#define DMAPI5_BRIDGE_PARAMETER_VERSION "version"
#define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage"
#define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel"
#define DMAPI5_BRIDGE_PARAMETER_EVENT_INVOCATION "eventInvocation"

#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort"
#define DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION "runtimeInformation"
Expand All @@ -48,6 +50,7 @@
#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision"
#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges"
#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel"
#define DMAPI5_RUNTIME_INFORMATION_VISIBILITY "visibility"

#define DMAPI5_CHAT_UPDATE_CHANNELS "channels"

Expand Down Expand Up @@ -79,6 +82,8 @@
#define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8
#define DMAPI5_TOPIC_COMMAND_SEND_CHUNK 9
#define DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK 10
#define DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST 11
#define DMAPI5_TOPIC_COMMAND_COMPLETE_EVENT 12

#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType"
#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand"
Expand All @@ -88,7 +93,9 @@
#define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName"
#define DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE "chatUpdate"
#define DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION "newServerVersion"
#define DMAPI5_TOPIC_PARAMETER_BROADCAST_MESSAGE "broadcastMessage"

#define DMAPI5_TOPIC_RESPONSE_CLIENT_COUNT "clientCount"
#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE "commandResponse"
#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage"
#define DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES "chatResponses"
Expand All @@ -113,3 +120,9 @@
#define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name"
#define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText"
#define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly"

#define DMAPI5_EVENT_ID "eventId"

#define DMAPI5_EVENT_INVOCATION_NAME "eventName"
#define DMAPI5_EVENT_INVOCATION_PARAMETERS "parameters"
#define DMAPI5_EVENT_INVOCATION_NOTIFY_COMPLETION "notifyCompletion"
Loading

0 comments on commit a2651a5

Please sign in to comment.