mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Updating TGS/DMAPI to version 4
This commit is contained in:
263
code/__defines/_tgs.dm
Normal file
263
code/__defines/_tgs.dm
Normal file
@@ -0,0 +1,263 @@
|
||||
//tgstation-server DMAPI
|
||||
|
||||
//All functions and datums outside this document are subject to change with any version and should not be relied on
|
||||
|
||||
//CONFIGURATION
|
||||
|
||||
//create this define if you want to do configuration outside of this file
|
||||
#ifndef TGS_EXTERNAL_CONFIGURATION
|
||||
|
||||
//Comment this out once you've filled in the below
|
||||
//#error TGS API unconfigured
|
||||
|
||||
//Uncomment this if you wish to allow the game to interact with TGS 3
|
||||
//This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()()
|
||||
//#define TGS_V3_API
|
||||
|
||||
//Required interfaces (fill in with your codebase equivalent):
|
||||
|
||||
//create a global variable named `Name` and set it to `Value`
|
||||
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name)
|
||||
|
||||
//Read the value in the global variable `Name`
|
||||
#define TGS_READ_GLOBAL(Name) GLOB.##Name
|
||||
|
||||
//Set the value in the global variable `Name` to `Value`
|
||||
#define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value
|
||||
|
||||
//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities
|
||||
#define TGS_PROTECT_DATUM(Path)
|
||||
|
||||
//Display an announcement `message` from the server to all players
|
||||
#define TGS_WORLD_ANNOUNCE(message) to_chat(world, "<span class='boldannounce'>[html_encode(##message)]</span>")
|
||||
|
||||
//Notify current in-game administrators of a string `event`
|
||||
#define TGS_NOTIFY_ADMINS(event) message_admins(##event)
|
||||
|
||||
//Write an info `message` to a server log
|
||||
#define TGS_INFO_LOG(message) log_world("SERVICE: [##message]")
|
||||
|
||||
//Write an error `message` to a server log
|
||||
#define TGS_ERROR_LOG(message)
|
||||
|
||||
//Get the number of connected /clients
|
||||
#define TGS_CLIENT_COUNT player_list.len
|
||||
|
||||
//Sends a message to connected game chats
|
||||
#define SERVER_TOOLS_CHAT_BROADCAST(message) world.TgsChatBroadcast(message)
|
||||
//Sends a message to connected admin chats
|
||||
#define SERVER_TOOLS_RELAY_BROADCAST(message) world.TgsTargetedChatBroadcast(message)
|
||||
|
||||
#endif
|
||||
|
||||
//EVENT CODES
|
||||
|
||||
#define TGS_EVENT_PORT_SWAP -2 //before a port change is about to happen, extra parameter is new port
|
||||
#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //before a reboot mode change, extras parameters are the current and new reboot mode enums
|
||||
|
||||
//See the descriptions for these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs
|
||||
#define TGS_EVENT_REPO_RESET_ORIGIN 0
|
||||
#define TGS_EVENT_REPO_CHECKOUT 1
|
||||
#define TGS_EVENT_REPO_FETCH 2
|
||||
#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3
|
||||
#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4
|
||||
#define TGS_EVENT_BYOND_INSTALL_START 5
|
||||
#define TGS_EVENT_BYOND_INSTALL_FAIL 6
|
||||
#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7
|
||||
#define TGS_EVENT_COMPILE_START 8
|
||||
#define TGS_EVENT_COMPILE_CANCELLED 9
|
||||
#define TGS_EVENT_COMPILE_FAILURE 10
|
||||
#define TGS_EVENT_COMPILE_COMPLETE 11
|
||||
#define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12
|
||||
#define TGS_EVENT_REPO_MERGE_CONFLICT 13
|
||||
|
||||
//OTHER ENUMS
|
||||
|
||||
#define TGS_REBOOT_MODE_NORMAL 0
|
||||
#define TGS_REBOOT_MODE_SHUTDOWN 1
|
||||
#define TGS_REBOOT_MODE_RESTART 2
|
||||
|
||||
#define TGS_SECURITY_TRUSTED 0
|
||||
#define TGS_SECURITY_SAFE 1
|
||||
#define TGS_SECURITY_ULTRASAFE 2
|
||||
|
||||
//REQUIRED HOOKS
|
||||
|
||||
//Call this somewhere in /world/New() that is always run
|
||||
//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels
|
||||
//minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated
|
||||
/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
|
||||
return
|
||||
|
||||
//Call this when your initializations are complete and your game is ready to play before any player interactions happen
|
||||
//This may use world.sleep_offline to make this happen so ensure no changes are made to it while this call is running
|
||||
//Most importantly, before this point, note that any static files or directories may be in use by another server. Your code should account for this
|
||||
//This function should not be called before ..() in /world/New()
|
||||
/world/proc/TgsInitializationComplete()
|
||||
return
|
||||
|
||||
//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
|
||||
|
||||
//Call this at the beginning of world/Reboot(reason)
|
||||
/world/proc/TgsReboot()
|
||||
return
|
||||
|
||||
//DATUM DEFINITIONS
|
||||
//unless otherwise specified all datums defined here should be considered read-only, warranty void if written
|
||||
|
||||
//represents git revision information about the current world build
|
||||
/datum/tgs_revision_information
|
||||
var/commit //full sha of compiled commit
|
||||
var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch
|
||||
|
||||
//represents a version of tgstation-server
|
||||
/datum/tgs_version
|
||||
var/suite //The suite version, can be >=3
|
||||
|
||||
//this group of variables can be null to represent a wild card
|
||||
var/major //The major version
|
||||
var/minor //The minor version
|
||||
var/patch //The patch version
|
||||
|
||||
var/raw_parameter //The unparsed parameter
|
||||
var/deprefixed_parameter //The version only bit of raw_parameter
|
||||
|
||||
//if the tgs_version is a wildcard version
|
||||
/datum/tgs_version/proc/Wildcard()
|
||||
return
|
||||
|
||||
//represents a merge of a GitHub pull request
|
||||
/datum/tgs_revision_information/test_merge
|
||||
var/number //pull request number
|
||||
var/title //pull request title
|
||||
var/body //pull request body
|
||||
var/author //pull request github author
|
||||
var/url //link to pull request html
|
||||
var/pull_request_commit //commit of the pull request when it was merged
|
||||
var/time_merged //timestamp of when the merge commit for the pull request was created
|
||||
var/comment //optional comment left by the one who initiated the test merge
|
||||
|
||||
//represents a connected chat channel
|
||||
/datum/tgs_chat_channel
|
||||
var/id //internal channel representation
|
||||
var/friendly_name //user friendly channel name
|
||||
var/connection_name //the name of the configured chat connection
|
||||
var/is_admin_channel //if the server operator has marked this channel for game admins only
|
||||
var/is_private_channel //if this is a private chat channel
|
||||
var/custom_tag //user defined string associated with channel
|
||||
|
||||
//represents a chat user
|
||||
/datum/tgs_chat_user
|
||||
var/id //Internal user representation, requires channel to be unique
|
||||
var/friendly_name //The user's public name
|
||||
var/mention //The text to use to ping this user in a message
|
||||
var/datum/tgs_chat_channel/channel //The /datum/tgs_chat_channel this user was from
|
||||
|
||||
//user definable callback for handling events
|
||||
//extra parameters may be specified depending on the event
|
||||
/datum/tgs_event_handler/proc/HandleEvent(event_code, ...)
|
||||
set waitfor = FALSE
|
||||
return
|
||||
|
||||
//user definable chat command
|
||||
/datum/tgs_chat_command
|
||||
var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command
|
||||
var/help_text = "" //help text for this command
|
||||
var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins
|
||||
|
||||
//override to implement command
|
||||
//sender: The tgs_chat_user who send to command
|
||||
//params: The trimmed string following the command name
|
||||
//The return value will be stringified and sent to the appropriate chat
|
||||
/datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params)
|
||||
CRASH("[type] has no implementation for Run()")
|
||||
|
||||
//FUNCTIONS
|
||||
|
||||
//Returns the respective supported /datum/tgs_version of the API
|
||||
/world/proc/TgsMaximumAPIVersion()
|
||||
return
|
||||
|
||||
/world/proc/TgsMinimumAPIVersion()
|
||||
return
|
||||
|
||||
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
|
||||
//No function below this succeeds if it returns FALSE
|
||||
/world/proc/TgsAvailable()
|
||||
return
|
||||
|
||||
//Gets the current /datum/tgs_version of the server tools running the server
|
||||
/world/proc/TgsVersion()
|
||||
return
|
||||
|
||||
//Gets the name of the TGS instance running the game
|
||||
/world/proc/TgsInstanceName()
|
||||
return
|
||||
|
||||
//Get the current `/datum/tgs_revision_information`
|
||||
/world/proc/TgsRevision()
|
||||
return
|
||||
|
||||
//Get the current BYOND security level
|
||||
/world/proc/TgsSecurityLevel()
|
||||
return
|
||||
|
||||
//Gets a list of active `/datum/tgs_revision_information/test_merge`s
|
||||
/world/proc/TgsTestMerges()
|
||||
return
|
||||
|
||||
//Forces a hard reboot of BYOND by ending the process
|
||||
//unlike del(world) clients will try to reconnect
|
||||
//If the service has not requested a shutdown, the next server will take over
|
||||
/world/proc/TgsEndProcess()
|
||||
return
|
||||
|
||||
//Gets a list of connected tgs_chat_channel
|
||||
/world/proc/TgsChatChannelInfo()
|
||||
return
|
||||
|
||||
//Sends a message to connected game chats
|
||||
//message: The message to send
|
||||
//channels: optional channels to limit the broadcast to
|
||||
/world/proc/TgsChatBroadcast(message, list/channels)
|
||||
return
|
||||
|
||||
//Send a message to non-admin connected chats
|
||||
//message: The message to send
|
||||
//admin_only: If TRUE, message will instead be sent to only admin connected chats
|
||||
/world/proc/TgsTargetedChatBroadcast(message, admin_only)
|
||||
return
|
||||
|
||||
//Send a private message to a specific user
|
||||
//message: The message to send
|
||||
//user: The /datum/tgs_chat_user to send to
|
||||
/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
@@ -1,101 +0,0 @@
|
||||
// /tg/station 13 server tools API
|
||||
#define SERVICE_API_VERSION_STRING "3.2.0.3"
|
||||
|
||||
//CONFIGURATION
|
||||
//use this define if you want to do configuration outside of this file
|
||||
//Required hooks:
|
||||
|
||||
//Put this somewhere in /world/New() that is always run
|
||||
#define SERVER_TOOLS_ON_NEW ServiceInit()
|
||||
//Put this somewhere in /world/Topic(T, Addr, Master, Keys) that is always run before T is modified
|
||||
#define SERVER_TOOLS_ON_TOPIC var/service_topic_return = ServiceCommand(params2list(T)); if(service_topic_return) return service_topic_return
|
||||
//Put at the beginning of world/Reboot(reason)
|
||||
#define SERVER_TOOLS_ON_REBOOT ServiceReboot()
|
||||
|
||||
//Optional callable functions:
|
||||
|
||||
//Returns the string version of the API
|
||||
#define SERVER_TOOLS_API_VERSION ServiceAPIVersion()
|
||||
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
|
||||
//No function below this succeed if this is FALSE
|
||||
#define SERVER_TOOLS_PRESENT RunningService()
|
||||
//Gets the current version of the service running the server
|
||||
#define SERVER_TOOLS_VERSION ServiceVersion()
|
||||
//Forces a hard reboot of BYOND by ending the process
|
||||
//unlike del(world) clients will try to reconnect
|
||||
//If the service has not requested a shutdown, the world will reboot shortly after
|
||||
#define SERVER_TOOLS_REBOOT_BYOND(silent) world.ServiceEndProcess(silent)
|
||||
/*
|
||||
Gets the list of any testmerged github pull requests
|
||||
"[PR Number]" => list(
|
||||
"title" -> PR title
|
||||
"commit" -> Full hash of commit merged
|
||||
"author" -> Github username of the author of the PR
|
||||
)
|
||||
*/
|
||||
#define SERVER_TOOLS_PR_LIST GetTestMerges()
|
||||
//Sends a message to connected game chats
|
||||
#define SERVER_TOOLS_CHAT_BROADCAST(message) world.ChatBroadcast(message)
|
||||
//Sends a message to connected admin chats
|
||||
#define SERVER_TOOLS_RELAY_BROADCAST(message) world.AdminBroadcast(message)
|
||||
|
||||
//IMPLEMENTATION
|
||||
|
||||
#define REBOOT_MODE_NORMAL 0
|
||||
#define REBOOT_MODE_HARD 1
|
||||
#define REBOOT_MODE_SHUTDOWN 2
|
||||
|
||||
#define SERVICE_WORLD_PARAM "server_service"
|
||||
#define SERVICE_VERSION_PARAM "server_service_version"
|
||||
#define SERVICE_INSTANCE_PARAM "server_instance"
|
||||
#define SERVICE_PR_TEST_JSON "prtestjob.json"
|
||||
#define SERVICE_INTERFACE_DLL "TGDreamDaemonBridge.dll"
|
||||
#define SERVICE_INTERFACE_FUNCTION "DDEntryPoint"
|
||||
|
||||
#define SERVICE_CMD_HARD_REBOOT "hard_reboot"
|
||||
#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown"
|
||||
#define SERVICE_CMD_WORLD_ANNOUNCE "world_announce"
|
||||
#define SERVICE_CMD_LIST_CUSTOM "list_custom_commands"
|
||||
#define SERVICE_CMD_API_COMPATIBLE "api_compat"
|
||||
#define SERVICE_CMD_PLAYER_COUNT "client_count"
|
||||
|
||||
#define SERVICE_CMD_PARAM_KEY "serviceCommsKey"
|
||||
#define SERVICE_CMD_PARAM_COMMAND "command"
|
||||
#define SERVICE_CMD_PARAM_SENDER "sender"
|
||||
#define SERVICE_CMD_PARAM_CUSTOM "custom"
|
||||
|
||||
#define SERVICE_JSON_PARAM_HELPTEXT "help_text"
|
||||
#define SERVICE_JSON_PARAM_ADMINONLY "admin_only"
|
||||
#define SERVICE_JSON_PARAM_REQUIREDPARAMETERS "required_parameters"
|
||||
|
||||
#define SERVICE_REQUEST_KILL_PROCESS "killme"
|
||||
#define SERVICE_REQUEST_KILL_PROCESS_SILENT "killmesilent"
|
||||
#define SERVICE_REQUEST_IRC_BROADCAST "irc"
|
||||
#define SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE "send2irc"
|
||||
#define SERVICE_REQUEST_WORLD_REBOOT "worldreboot"
|
||||
#define SERVICE_REQUEST_API_VERSION "api_ver"
|
||||
|
||||
#define SERVICE_RETURN_SUCCESS "SUCCESS"
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
@@ -1,11 +1,11 @@
|
||||
/world/New()
|
||||
SERVER_TOOLS_ON_NEW
|
||||
return ..()
|
||||
..()
|
||||
TgsNew()
|
||||
|
||||
/world/Reboot(var/reason)
|
||||
SERVER_TOOLS_ON_REBOOT
|
||||
return ..(reason)
|
||||
/world/Reboot()
|
||||
TgsReboot()
|
||||
..()
|
||||
|
||||
/world/Topic(T, addr, master, key)
|
||||
SERVER_TOOLS_ON_TOPIC
|
||||
return ..(T, addr, master, key)
|
||||
/world/Topic()
|
||||
TGS_TOPIC
|
||||
..()
|
||||
@@ -1,72 +0,0 @@
|
||||
/datum/server_tools_command
|
||||
var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command
|
||||
var/help_text = "" //help text for this command
|
||||
var/required_parameters = 0 //number of parameters required for this command
|
||||
var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins
|
||||
|
||||
//override to implement command
|
||||
//sender is the display name of who sent the command
|
||||
//params is the trimmed string following the command name
|
||||
/datum/server_tools_command/proc/Run(sender, params)
|
||||
CRASH("[type] has no implementation for Run()")
|
||||
|
||||
/world/proc/ListServiceCustomCommands(warnings_only)
|
||||
if(!warnings_only)
|
||||
. = list()
|
||||
var/list/command_name_types = list()
|
||||
var/list/warned_command_names = warnings_only ? list() : null
|
||||
for(var/I in typesof(/datum/server_tools_command) - /datum/server_tools_command)
|
||||
var/datum/server_tools_command/stc = I
|
||||
var/command_name = initial(stc.name)
|
||||
var/static/list/warned_server_tools_names = list()
|
||||
if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\""))
|
||||
if(warnings_only && !warned_command_names[command_name])
|
||||
SERVER_TOOLS_LOG("WARNING: Custom command [command_name] cannot be used as it is empty or contains illegal characters!")
|
||||
warned_command_names[command_name] = TRUE
|
||||
continue
|
||||
|
||||
if(command_name_types[command_name])
|
||||
if(warnings_only)
|
||||
SERVER_TOOLS_LOG("WARNING: Custom commands [command_name_types[command_name]] and [stc] have the same name only [command_name_types[command_name]] will be available!")
|
||||
continue
|
||||
command_name_types[stc] = command_name
|
||||
|
||||
if(!warnings_only)
|
||||
.[command_name] = list(SERVICE_JSON_PARAM_HELPTEXT = initial(stc.help_text), SERVICE_JSON_PARAM_ADMINONLY = initial(stc.admin_only), SERVICE_JSON_PARAM_REQUIREDPARAMETERS = initial(stc.required_parameters))
|
||||
|
||||
/world/proc/HandleServiceCustomCommand(command, sender, params)
|
||||
var/static/list/cached_custom_server_tools_commands
|
||||
if(!cached_custom_server_tools_commands)
|
||||
cached_custom_server_tools_commands = list()
|
||||
for(var/I in typesof(/datum/server_tools_command) - /datum/server_tools_command)
|
||||
var/datum/server_tools_command/stc = I
|
||||
cached_custom_server_tools_commands[lowertext(initial(stc.name))] = stc
|
||||
|
||||
var/command_type = cached_custom_server_tools_commands[command]
|
||||
if(!command_type)
|
||||
return FALSE
|
||||
var/datum/server_tools_command/stc = new command_type
|
||||
return stc.Run(sender, params) || TRUE
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
@@ -1,131 +0,0 @@
|
||||
SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(reboot_mode, REBOOT_MODE_NORMAL)
|
||||
SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
|
||||
|
||||
/proc/GetTestMerges()
|
||||
if(RunningService(TRUE) && fexists(SERVICE_PR_TEST_JSON))
|
||||
. = json_decode(file2text(SERVICE_PR_TEST_JSON))
|
||||
if(.)
|
||||
return
|
||||
return list()
|
||||
|
||||
/world/proc/ServiceInit()
|
||||
if(!RunningService(TRUE))
|
||||
return
|
||||
ListServiceCustomCommands(TRUE)
|
||||
ExportService("[SERVICE_REQUEST_API_VERSION] [SERVER_TOOLS_API_VERSION]", TRUE)
|
||||
|
||||
/proc/RunningService(skip_compat_check = FALSE)
|
||||
if(!skip_compat_check && !SERVER_TOOLS_READ_GLOBAL(server_tools_api_compatible))
|
||||
return FALSE
|
||||
. = world.params[SERVICE_WORLD_PARAM] != null
|
||||
if(. && world.system_type != MS_WINDOWS)
|
||||
SERVER_TOOLS_LOG("Warning: Server tools world parameter detected but not running on Windows. Aborting initialization!")
|
||||
return FALSE
|
||||
|
||||
/proc/ServiceVersion()
|
||||
if(RunningService(TRUE))
|
||||
return world.params[SERVICE_VERSION_PARAM]
|
||||
|
||||
/proc/ServiceAPIVersion()
|
||||
return SERVICE_API_VERSION_STRING
|
||||
|
||||
/world/proc/ExportService(command, skip_compat_check = FALSE)
|
||||
. = FALSE
|
||||
if(!RunningService(skip_compat_check))
|
||||
return
|
||||
if(skip_compat_check && !fexists(SERVICE_INTERFACE_DLL))
|
||||
CRASH("Service parameter present but no interface DLL detected. This is symptomatic of running a service less than version 3.1! Please upgrade.")
|
||||
var/instance = params[SERVICE_INSTANCE_PARAM]
|
||||
if(!instance)
|
||||
instance = "TG Station Server" //maybe just upgraded
|
||||
call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance, command) //trust no retval
|
||||
return TRUE
|
||||
|
||||
/world/proc/ChatBroadcast(message)
|
||||
ExportService("[SERVICE_REQUEST_IRC_BROADCAST] [message]")
|
||||
|
||||
/world/proc/AdminBroadcast(message)
|
||||
ExportService("[SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE] [message]")
|
||||
|
||||
/world/proc/ServiceEndProcess(silent = FALSE)
|
||||
SERVER_TOOLS_LOG("Sending shutdown request!");
|
||||
sleep(world.tick_lag) //flush the buffers
|
||||
ExportService(silent ? SERVICE_REQUEST_KILL_PROCESS_SILENT : SERVICE_REQUEST_KILL_PROCESS)
|
||||
|
||||
//called at the exact moment the world is supposed to reboot
|
||||
/world/proc/ServiceReboot()
|
||||
switch(SERVER_TOOLS_READ_GLOBAL(reboot_mode))
|
||||
if(REBOOT_MODE_HARD)
|
||||
SERVER_TOOLS_WORLD_ANNOUNCE("gay")//Hard reboot triggered, you will automatically reconnect...")
|
||||
ServiceEndProcess()
|
||||
if(REBOOT_MODE_SHUTDOWN)
|
||||
SERVER_TOOLS_WORLD_ANNOUNCE("The server is shutting down...")
|
||||
ServiceEndProcess()
|
||||
else
|
||||
ExportService(SERVICE_REQUEST_WORLD_REBOOT) //just let em know
|
||||
|
||||
/world/proc/ServiceCommand(list/params)
|
||||
var/their_sCK = params[SERVICE_CMD_PARAM_KEY]
|
||||
if(!their_sCK || !RunningService(TRUE))
|
||||
return FALSE //continue world/Topic
|
||||
|
||||
var/sCK = world.params[SERVICE_WORLD_PARAM]
|
||||
if(their_sCK != sCK)
|
||||
return "Invalid comms key!";
|
||||
|
||||
var/command = params[SERVICE_CMD_PARAM_COMMAND]
|
||||
if(!command)
|
||||
return "No command!"
|
||||
|
||||
switch(command)
|
||||
if(SERVICE_CMD_API_COMPATIBLE)
|
||||
SERVER_TOOLS_WRITE_GLOBAL(server_tools_api_compatible, TRUE)
|
||||
return SERVICE_RETURN_SUCCESS
|
||||
if(SERVICE_CMD_HARD_REBOOT)
|
||||
if(SERVER_TOOLS_READ_GLOBAL(reboot_mode) != REBOOT_MODE_HARD)
|
||||
SERVER_TOOLS_WRITE_GLOBAL(reboot_mode, REBOOT_MODE_HARD)
|
||||
SERVER_TOOLS_LOG("Hard reboot requested by service")
|
||||
SERVER_TOOLS_NOTIFY_ADMINS("The world will hard reboot at the end of the game. Requested by service.")
|
||||
if(SERVICE_CMD_GRACEFUL_SHUTDOWN)
|
||||
if(SERVER_TOOLS_READ_GLOBAL(reboot_mode) != REBOOT_MODE_SHUTDOWN)
|
||||
SERVER_TOOLS_WRITE_GLOBAL(reboot_mode, REBOOT_MODE_SHUTDOWN)
|
||||
SERVER_TOOLS_LOG("Shutdown requested by service")
|
||||
message_admins("The world will shutdown at the end of the game. Requested by service.")
|
||||
if(SERVICE_CMD_WORLD_ANNOUNCE)
|
||||
var/msg = params["message"]
|
||||
if(!istext(msg) || !msg)
|
||||
return "No message set!"
|
||||
SERVER_TOOLS_WORLD_ANNOUNCE(msg)
|
||||
return SERVICE_RETURN_SUCCESS
|
||||
if(SERVICE_CMD_PLAYER_COUNT)
|
||||
return "[SERVER_TOOLS_CLIENT_COUNT]"
|
||||
if(SERVICE_CMD_LIST_CUSTOM)
|
||||
return json_encode(ListServiceCustomCommands(FALSE))
|
||||
else
|
||||
var/custom_command_result = HandleServiceCustomCommand(lowertext(command), params[SERVICE_CMD_PARAM_SENDER], params[SERVICE_CMD_PARAM_CUSTOM])
|
||||
if(custom_command_result)
|
||||
return istext(custom_command_result) ? custom_command_result : SERVICE_RETURN_SUCCESS
|
||||
return "Unknown command: [command]"
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
2
code/modules/DMAPI/tgs/core/_definitions.dm
Normal file
2
code/modules/DMAPI/tgs/core/_definitions.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
#define TGS_UNIMPLEMENTED "___unimplemented"
|
||||
#define TGS_VERSION_PARAMETER "server_service_version"
|
||||
164
code/modules/DMAPI/tgs/core/core.dm
Normal file
164
code/modules/DMAPI/tgs/core/core.dm
Normal file
@@ -0,0 +1,164 @@
|
||||
/world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
|
||||
var/current_api = TGS_READ_GLOBAL(tgs)
|
||||
if(current_api)
|
||||
TGS_ERROR_LOG("TgsNew(): TGS API datum already set ([current_api])! Was TgsNew() called more than once?")
|
||||
return
|
||||
|
||||
#ifdef TGS_V3_API
|
||||
minimum_required_security_level = TGS_SECURITY_TRUSTED
|
||||
#endif
|
||||
var/raw_parameter = world.params[TGS_VERSION_PARAMETER]
|
||||
if(!raw_parameter)
|
||||
return
|
||||
|
||||
var/datum/tgs_version/version = new(raw_parameter)
|
||||
if(!version.Valid(FALSE))
|
||||
TGS_ERROR_LOG("Failed to validate TGS version parameter: [raw_parameter]!")
|
||||
return
|
||||
|
||||
var/api_datum
|
||||
switch(version.suite)
|
||||
if(3)
|
||||
#ifndef TGS_V3_API
|
||||
TGS_ERROR_LOG("Detected V3 API but TGS_V3_API isn't defined!")
|
||||
#else
|
||||
switch(version.major)
|
||||
if(2)
|
||||
api_datum = /datum/tgs_api/v3210
|
||||
#endif
|
||||
if(4)
|
||||
switch(version.major)
|
||||
if(0)
|
||||
api_datum = /datum/tgs_api/v4
|
||||
|
||||
var/datum/tgs_version/max_api_version = TgsMaximumAPIVersion();
|
||||
if(version.suite != null && version.major != null && version.minor != null && version.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.")
|
||||
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.")
|
||||
return
|
||||
|
||||
TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]")
|
||||
var/datum/tgs_api/new_api = new api_datum(version)
|
||||
|
||||
TGS_WRITE_GLOBAL(tgs, new_api)
|
||||
|
||||
var/result = new_api.OnWorldNew(event_handler, minimum_required_security_level)
|
||||
if(!result || result == TGS_UNIMPLEMENTED)
|
||||
TGS_WRITE_GLOBAL(tgs, null)
|
||||
TGS_ERROR_LOG("Failed to activate API!")
|
||||
|
||||
/world/TgsMaximumAPIVersion()
|
||||
return new /datum/tgs_version("4.0.x.x")
|
||||
|
||||
/world/TgsMinimumAPIVersion()
|
||||
return new /datum/tgs_version("3.2.0.0")
|
||||
|
||||
/world/TgsInitializationComplete()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.OnInitializationComplete()
|
||||
|
||||
/world/proc/TgsTopic(T)
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
var/result = api.OnTopic(T)
|
||||
if(result != TGS_UNIMPLEMENTED)
|
||||
return result
|
||||
|
||||
/world/TgsRevision()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
var/result = api.Revision()
|
||||
if(result != TGS_UNIMPLEMENTED)
|
||||
return result
|
||||
|
||||
/world/TgsReboot()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.OnReboot()
|
||||
|
||||
/world/TgsAvailable()
|
||||
return TGS_READ_GLOBAL(tgs) != null
|
||||
|
||||
/world/TgsVersion()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
return api.version
|
||||
|
||||
/world/TgsInstanceName()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
var/result = api.InstanceName()
|
||||
if(result != TGS_UNIMPLEMENTED)
|
||||
return result
|
||||
|
||||
/world/TgsTestMerges()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
var/result = api.TestMerges()
|
||||
if(result != TGS_UNIMPLEMENTED)
|
||||
return result
|
||||
return list()
|
||||
|
||||
/world/TgsEndProcess()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.EndProcess()
|
||||
|
||||
/world/TgsChatChannelInfo()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
var/result = api.ChatChannelInfo()
|
||||
if(result != TGS_UNIMPLEMENTED)
|
||||
return result
|
||||
return list()
|
||||
|
||||
/world/TgsChatBroadcast(message, list/channels)
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.ChatBroadcast(message, channels)
|
||||
|
||||
/world/TgsTargetedChatBroadcast(message, admin_only)
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.ChatTargetedBroadcast(message, admin_only)
|
||||
|
||||
/world/TgsChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.ChatPrivateMessage(message, user)
|
||||
|
||||
/world/TgsSecurityLevel()
|
||||
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
|
||||
if(api)
|
||||
api.SecurityLevel()
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
82
code/modules/DMAPI/tgs/core/datum.dm
Normal file
82
code/modules/DMAPI/tgs/core/datum.dm
Normal file
@@ -0,0 +1,82 @@
|
||||
TGS_DEFINE_AND_SET_GLOBAL(tgs, null)
|
||||
|
||||
/datum/tgs_api
|
||||
var/datum/tgs_version/version
|
||||
|
||||
/datum/tgs_api/New(datum/tgs_version/version)
|
||||
. = ..()
|
||||
src.version = version
|
||||
|
||||
/datum/tgs_api/latest
|
||||
parent_type = /datum/tgs_api/v4
|
||||
|
||||
TGS_PROTECT_DATUM(/datum/tgs_api)
|
||||
|
||||
/datum/tgs_api/proc/ApiVersion()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/OnWorldNew(datum/tgs_event_handler/event_handler)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/OnInitializationComplete()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/OnTopic(T)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/OnReboot()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/InstanceName()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/TestMerges()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/EndProcess()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/Revision()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/ChatChannelInfo()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/ChatBroadcast(message, list/channels)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/ChatTargetedBroadcast(message, admin_only)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/ChatPrivateMessage(message, admin_only)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/proc/SecurityLevel()
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
22
code/modules/DMAPI/tgs/core/tgs_version.dm
Normal file
22
code/modules/DMAPI/tgs/core/tgs_version.dm
Normal file
@@ -0,0 +1,22 @@
|
||||
/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, ".")
|
||||
|
||||
suite = text2num(version_bits[1])
|
||||
if(version_bits.len > 1)
|
||||
major = text2num(version_bits[2])
|
||||
if(version_bits.len > 2)
|
||||
minor = text2num(version_bits[3])
|
||||
if(version_bits.len == 4)
|
||||
patch = text2num(version_bits[4])
|
||||
|
||||
/datum/tgs_version/proc/Valid(allow_wildcards = FALSE)
|
||||
if(suite == null)
|
||||
return FALSE
|
||||
if(allow_wildcards)
|
||||
return TRUE
|
||||
return !Wildcard()
|
||||
|
||||
/datum/tgs_version/Wildcard()
|
||||
return major == null || minor == null || patch == null
|
||||
10
code/modules/DMAPI/tgs/includes.dm
Normal file
10
code/modules/DMAPI/tgs/includes.dm
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "core\_definitions.dm"
|
||||
#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"
|
||||
253
code/modules/DMAPI/tgs/v3210/api.dm
Normal file
253
code/modules/DMAPI/tgs/v3210/api.dm
Normal file
@@ -0,0 +1,253 @@
|
||||
#define REBOOT_MODE_NORMAL 0
|
||||
#define REBOOT_MODE_HARD 1
|
||||
#define REBOOT_MODE_SHUTDOWN 2
|
||||
|
||||
#define SERVICE_WORLD_PARAM "server_service"
|
||||
#define SERVICE_INSTANCE_PARAM "server_instance"
|
||||
#define SERVICE_PR_TEST_JSON "prtestjob.json"
|
||||
#define SERVICE_INTERFACE_DLL "TGDreamDaemonBridge.dll"
|
||||
#define SERVICE_INTERFACE_FUNCTION "DDEntryPoint"
|
||||
|
||||
#define SERVICE_CMD_HARD_REBOOT "hard_reboot"
|
||||
#define SERVICE_CMD_GRACEFUL_SHUTDOWN "graceful_shutdown"
|
||||
#define SERVICE_CMD_WORLD_ANNOUNCE "world_announce"
|
||||
#define SERVICE_CMD_LIST_CUSTOM "list_custom_commands"
|
||||
#define SERVICE_CMD_API_COMPATIBLE "api_compat"
|
||||
#define SERVICE_CMD_PLAYER_COUNT "client_count"
|
||||
|
||||
#define SERVICE_CMD_PARAM_KEY "serviceCommsKey"
|
||||
#define SERVICE_CMD_PARAM_COMMAND "command"
|
||||
#define SERVICE_CMD_PARAM_SENDER "sender"
|
||||
#define SERVICE_CMD_PARAM_CUSTOM "custom"
|
||||
|
||||
#define SERVICE_REQUEST_KILL_PROCESS "killme"
|
||||
#define SERVICE_REQUEST_IRC_BROADCAST "irc"
|
||||
#define SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE "send2irc"
|
||||
#define SERVICE_REQUEST_WORLD_REBOOT "worldreboot"
|
||||
#define SERVICE_REQUEST_API_VERSION "api_ver"
|
||||
|
||||
#define SERVICE_RETURN_SUCCESS "SUCCESS"
|
||||
|
||||
/datum/tgs_api/v3210
|
||||
var/reboot_mode = REBOOT_MODE_NORMAL
|
||||
var/comms_key
|
||||
var/instance_name
|
||||
var/originmastercommit
|
||||
var/commit
|
||||
var/list/cached_custom_tgs_chat_commands
|
||||
var/warned_revison = FALSE
|
||||
var/warned_custom_commands = FALSE
|
||||
|
||||
/datum/tgs_api/v3210/ApiVersion()
|
||||
return "3.2.1.0"
|
||||
|
||||
/datum/tgs_api/v3210/proc/trim_left(text)
|
||||
for (var/i = 1 to length(text))
|
||||
if (text2ascii(text, i) > 32)
|
||||
return copytext(text, i)
|
||||
return ""
|
||||
|
||||
/datum/tgs_api/v3210/proc/trim_right(text)
|
||||
for (var/i = length(text), i > 0, i--)
|
||||
if (text2ascii(text, i) > 32)
|
||||
return copytext(text, 1, i + 1)
|
||||
return ""
|
||||
|
||||
/datum/tgs_api/v3210/proc/file2list(filename)
|
||||
return splittext(trim_left(trim_right(file2text(filename))), "\n")
|
||||
|
||||
/datum/tgs_api/v3210/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) //don't use event handling in this version
|
||||
. = FALSE
|
||||
|
||||
comms_key = world.params[SERVICE_WORLD_PARAM]
|
||||
instance_name = world.params[SERVICE_INSTANCE_PARAM]
|
||||
if(!instance_name)
|
||||
instance_name = "TG Station Server" //maybe just upgraded
|
||||
|
||||
var/list/logs = file2list(".git/logs/HEAD")
|
||||
if(logs.len)
|
||||
logs = splittext(logs[logs.len - 1], " ")
|
||||
commit = logs[2]
|
||||
logs = file2list(".git/logs/refs/remotes/origin/master")
|
||||
if(logs.len)
|
||||
originmastercommit = splittext(logs[logs.len - 1], " ")[2]
|
||||
|
||||
if(world.system_type != MS_WINDOWS)
|
||||
TGS_ERROR_LOG("This API version is only supported on Windows. Not running on Windows. Aborting initialization!")
|
||||
return
|
||||
ListServiceCustomCommands(TRUE)
|
||||
ExportService("[SERVICE_REQUEST_API_VERSION] [ApiVersion()]", TRUE)
|
||||
return TRUE
|
||||
|
||||
//nothing to do for v3
|
||||
/datum/tgs_api/v3210/OnInitializationComplete()
|
||||
return
|
||||
|
||||
/datum/tgs_api/v3210/InstanceName()
|
||||
return world.params[SERVICE_INSTANCE_PARAM]
|
||||
|
||||
/datum/tgs_api/v3210/proc/ExportService(command, skip_compat_check = FALSE)
|
||||
. = FALSE
|
||||
if(skip_compat_check && !fexists(SERVICE_INTERFACE_DLL))
|
||||
TGS_ERROR_LOG("Service parameter present but no interface DLL detected. This is symptomatic of running a service less than version 3.1! Please upgrade.")
|
||||
return
|
||||
call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance_name, command) //trust no retval
|
||||
return TRUE
|
||||
|
||||
/datum/tgs_api/v3210/OnTopic(T)
|
||||
var/list/params = params2list(T)
|
||||
var/their_sCK = params[SERVICE_CMD_PARAM_KEY]
|
||||
if(!their_sCK)
|
||||
return FALSE //continue world/Topic
|
||||
|
||||
if(their_sCK != comms_key)
|
||||
return "Invalid comms key!";
|
||||
|
||||
var/command = params[SERVICE_CMD_PARAM_COMMAND]
|
||||
if(!command)
|
||||
return "No command!"
|
||||
|
||||
switch(command)
|
||||
if(SERVICE_CMD_API_COMPATIBLE)
|
||||
return SERVICE_RETURN_SUCCESS
|
||||
if(SERVICE_CMD_HARD_REBOOT)
|
||||
if(reboot_mode != REBOOT_MODE_HARD)
|
||||
reboot_mode = REBOOT_MODE_HARD
|
||||
TGS_INFO_LOG("Hard reboot requested by service")
|
||||
TGS_NOTIFY_ADMINS("The world will hard reboot at the end of the game. Requested by TGS.")
|
||||
if(SERVICE_CMD_GRACEFUL_SHUTDOWN)
|
||||
if(reboot_mode != REBOOT_MODE_SHUTDOWN)
|
||||
reboot_mode = REBOOT_MODE_SHUTDOWN
|
||||
TGS_INFO_LOG("Shutdown requested by service")
|
||||
TGS_NOTIFY_ADMINS("The world will shutdown at the end of the game. Requested by TGS.")
|
||||
if(SERVICE_CMD_WORLD_ANNOUNCE)
|
||||
var/msg = params["message"]
|
||||
if(!istext(msg) || !msg)
|
||||
return "No message set!"
|
||||
TGS_WORLD_ANNOUNCE(msg)
|
||||
return SERVICE_RETURN_SUCCESS
|
||||
if(SERVICE_CMD_PLAYER_COUNT)
|
||||
return "[TGS_CLIENT_COUNT]"
|
||||
if(SERVICE_CMD_LIST_CUSTOM)
|
||||
return json_encode(ListServiceCustomCommands(FALSE))
|
||||
else
|
||||
var/custom_command_result = HandleServiceCustomCommand(lowertext(command), params[SERVICE_CMD_PARAM_SENDER], params[SERVICE_CMD_PARAM_CUSTOM])
|
||||
if(custom_command_result)
|
||||
return istext(custom_command_result) ? custom_command_result : SERVICE_RETURN_SUCCESS
|
||||
return "Unknown command: [command]"
|
||||
|
||||
/datum/tgs_api/v3210/OnReboot()
|
||||
switch(reboot_mode)
|
||||
if(REBOOT_MODE_HARD)
|
||||
TGS_WORLD_ANNOUNCE("Hard reboot triggered, you will automatically reconnect...")
|
||||
EndProcess()
|
||||
if(REBOOT_MODE_SHUTDOWN)
|
||||
TGS_WORLD_ANNOUNCE("The server is shutting down...")
|
||||
EndProcess()
|
||||
else
|
||||
ExportService(SERVICE_REQUEST_WORLD_REBOOT) //just let em know
|
||||
|
||||
/datum/tgs_api/v3210/TestMerges()
|
||||
//do the best we can here as the datum can't be completed using the v3 api
|
||||
. = list()
|
||||
if(!fexists(SERVICE_PR_TEST_JSON))
|
||||
return
|
||||
var/list/json = json_decode(file2text(SERVICE_PR_TEST_JSON))
|
||||
if(!json)
|
||||
return
|
||||
for(var/I in json)
|
||||
var/datum/tgs_revision_information/test_merge/tm = new
|
||||
tm.number = text2num(I)
|
||||
var/list/entry = json[I]
|
||||
tm.pull_request_commit = entry["commit"]
|
||||
tm.author = entry["author"]
|
||||
tm.title = entry["title"]
|
||||
. += tm
|
||||
|
||||
/datum/tgs_api/v3210/Revision()
|
||||
if(!warned_revison)
|
||||
TGS_ERROR_LOG("Use of TgsRevision on [ApiVersion()] origin_commit only points to master!")
|
||||
warned_revison = TRUE
|
||||
var/datum/tgs_revision_information/ri = new
|
||||
ri.commit = commit
|
||||
ri.origin_commit = originmastercommit
|
||||
return ri
|
||||
|
||||
/datum/tgs_api/v3210/EndProcess()
|
||||
sleep(world.tick_lag) //flush the buffers
|
||||
ExportService(SERVICE_REQUEST_KILL_PROCESS)
|
||||
|
||||
/datum/tgs_api/v3210/ChatChannelInfo()
|
||||
return list()
|
||||
|
||||
/datum/tgs_api/v3210/ChatBroadcast(message, list/channels)
|
||||
if(channels)
|
||||
return TGS_UNIMPLEMENTED
|
||||
ChatTargetedBroadcast(message, TRUE)
|
||||
ChatTargetedBroadcast(message, FALSE)
|
||||
|
||||
/datum/tgs_api/v3210/ChatTargetedBroadcast(message, admin_only)
|
||||
ExportService("[admin_only ? SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE : SERVICE_REQUEST_IRC_BROADCAST] [message]")
|
||||
|
||||
/datum/tgs_api/v3210/ChatPrivateMessage(message, datum/tgs_chat_user/user)
|
||||
return TGS_UNIMPLEMENTED
|
||||
|
||||
/datum/tgs_api/v3210/SecurityLevel()
|
||||
return TGS_SECURITY_TRUSTED
|
||||
|
||||
#undef REBOOT_MODE_NORMAL
|
||||
#undef REBOOT_MODE_HARD
|
||||
#undef REBOOT_MODE_SHUTDOWN
|
||||
|
||||
#undef SERVICE_WORLD_PARAM
|
||||
#undef SERVICE_INSTANCE_PARAM
|
||||
#undef SERVICE_PR_TEST_JSON
|
||||
#undef SERVICE_INTERFACE_DLL
|
||||
#undef SERVICE_INTERFACE_FUNCTION
|
||||
|
||||
#undef SERVICE_CMD_HARD_REBOOT
|
||||
#undef SERVICE_CMD_GRACEFUL_SHUTDOWN
|
||||
#undef SERVICE_CMD_WORLD_ANNOUNCE
|
||||
#undef SERVICE_CMD_LIST_CUSTOM
|
||||
#undef SERVICE_CMD_API_COMPATIBLE
|
||||
#undef SERVICE_CMD_PLAYER_COUNT
|
||||
|
||||
#undef SERVICE_CMD_PARAM_KEY
|
||||
#undef SERVICE_CMD_PARAM_COMMAND
|
||||
#undef SERVICE_CMD_PARAM_SENDER
|
||||
#undef SERVICE_CMD_PARAM_CUSTOM
|
||||
|
||||
#undef SERVICE_REQUEST_KILL_PROCESS
|
||||
#undef SERVICE_REQUEST_IRC_BROADCAST
|
||||
#undef SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE
|
||||
#undef SERVICE_REQUEST_WORLD_REBOOT
|
||||
#undef SERVICE_REQUEST_API_VERSION
|
||||
|
||||
#undef SERVICE_RETURN_SUCCESS
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
78
code/modules/DMAPI/tgs/v3210/commands.dm
Normal file
78
code/modules/DMAPI/tgs/v3210/commands.dm
Normal file
@@ -0,0 +1,78 @@
|
||||
#define SERVICE_JSON_PARAM_HELPTEXT "help_text"
|
||||
#define SERVICE_JSON_PARAM_ADMINONLY "admin_only"
|
||||
#define SERVICE_JSON_PARAM_REQUIREDPARAMETERS "required_parameters"
|
||||
|
||||
/datum/tgs_api/v3210/proc/ListServiceCustomCommands(warnings_only)
|
||||
if(!warnings_only)
|
||||
. = list()
|
||||
var/list/command_name_types = list()
|
||||
var/list/warned_command_names = warnings_only ? list() : null
|
||||
var/warned_about_the_dangers_of_robutussin = !warnings_only
|
||||
for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command)
|
||||
if(!warned_about_the_dangers_of_robutussin)
|
||||
TGS_ERROR_LOG("Custom chat commands in [ApiVersion()] lacks the /datum/tgs_chat_user/sender.channel field!")
|
||||
warned_about_the_dangers_of_robutussin = TRUE
|
||||
var/datum/tgs_chat_command/stc = I
|
||||
var/command_name = initial(stc.name)
|
||||
if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\""))
|
||||
if(warnings_only && !warned_command_names[command_name])
|
||||
TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!")
|
||||
warned_command_names[command_name] = TRUE
|
||||
continue
|
||||
|
||||
if(command_name_types[command_name])
|
||||
if(warnings_only)
|
||||
TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!")
|
||||
continue
|
||||
command_name_types[stc] = command_name
|
||||
|
||||
if(!warnings_only)
|
||||
.[command_name] = list(SERVICE_JSON_PARAM_HELPTEXT = initial(stc.help_text), SERVICE_JSON_PARAM_ADMINONLY = initial(stc.admin_only), SERVICE_JSON_PARAM_REQUIREDPARAMETERS = 0)
|
||||
|
||||
/datum/tgs_api/v3210/proc/HandleServiceCustomCommand(command, sender, params)
|
||||
if(!cached_custom_tgs_chat_commands)
|
||||
cached_custom_tgs_chat_commands = list()
|
||||
for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command)
|
||||
var/datum/tgs_chat_command/stc = I
|
||||
cached_custom_tgs_chat_commands[lowertext(initial(stc.name))] = stc
|
||||
|
||||
var/command_type = cached_custom_tgs_chat_commands[command]
|
||||
if(!command_type)
|
||||
return FALSE
|
||||
var/datum/tgs_chat_command/stc = new command_type
|
||||
var/datum/tgs_chat_user/user = new
|
||||
user.friendly_name = sender
|
||||
user.mention = sender
|
||||
return stc.Run(user, params) || TRUE
|
||||
|
||||
/*
|
||||
|
||||
#undef SERVICE_JSON_PARAM_HELPTEXT
|
||||
#undef SERVICE_JSON_PARAM_ADMINONLY
|
||||
#undef SERVICE_JSON_PARAM_REQUIREDPARAMETERS
|
||||
|
||||
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.
|
||||
*/
|
||||
342
code/modules/DMAPI/tgs/v4/api.dm
Normal file
342
code/modules/DMAPI/tgs/v4/api.dm
Normal file
@@ -0,0 +1,342 @@
|
||||
#define TGS4_PARAM_INFO_JSON "tgs_json"
|
||||
|
||||
#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/v4
|
||||
var/access_identifier
|
||||
var/instance_name
|
||||
var/json_path
|
||||
var/chat_channels_json_path
|
||||
var/chat_commands_json_path
|
||||
var/server_commands_json_path
|
||||
var/reboot_mode = TGS_REBOOT_MODE_NORMAL
|
||||
var/security_level
|
||||
|
||||
var/requesting_new_port = FALSE
|
||||
|
||||
var/list/intercepted_message_queue
|
||||
|
||||
var/list/custom_commands
|
||||
|
||||
var/list/cached_test_merges
|
||||
var/datum/tgs_revision_information/cached_revision
|
||||
|
||||
var/datum/tgs_event_handler/event_handler
|
||||
|
||||
var/export_lock = FALSE
|
||||
var/list/last_interop_response
|
||||
|
||||
/datum/tgs_api/v4/ApiVersion()
|
||||
return "4.0.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]
|
||||
if(!json_path)
|
||||
TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!")
|
||||
return
|
||||
var/json_file = file2text(json_path)
|
||||
if(!json_file)
|
||||
TGS_ERROR_LOG("Missing specified json file: [json_path]")
|
||||
return
|
||||
var/cached_json = json_decode(json_file)
|
||||
if(!cached_json)
|
||||
TGS_ERROR_LOG("Failed to decode info json: [json_file]")
|
||||
return
|
||||
|
||||
access_identifier = cached_json["accessIdentifier"]
|
||||
server_commands_json_path = cached_json["serverCommandsJson"]
|
||||
|
||||
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)
|
||||
|
||||
security_level = cached_json["securityLevel"]
|
||||
chat_channels_json_path = cached_json["chatChannelsJson"]
|
||||
chat_commands_json_path = cached_json["chatCommandsJson"]
|
||||
src.event_handler = event_handler
|
||||
instance_name = cached_json["instanceName"]
|
||||
|
||||
ListCustomCommands()
|
||||
|
||||
var/list/revisionData = cached_json["revision"]
|
||||
if(revisionData)
|
||||
cached_revision = new
|
||||
cached_revision.commit = revisionData["commitSha"]
|
||||
cached_revision.origin_commit = revisionData["originCommitSha"]
|
||||
|
||||
cached_test_merges = list()
|
||||
var/list/json = cached_json["testMerges"]
|
||||
for(var/entry in json)
|
||||
var/datum/tgs_revision_information/test_merge/tm = new
|
||||
tm.time_merged = text2num(entry["timeMerged"])
|
||||
|
||||
var/list/revInfo = entry["revision"]
|
||||
if(revInfo)
|
||||
tm.commit = revInfo["commitSha"]
|
||||
tm.origin_commit = revInfo["originCommitSha"]
|
||||
|
||||
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"]
|
||||
|
||||
cached_test_merges += tm
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/tgs_api/v4/OnInitializationComplete()
|
||||
Export(TGS4_COMM_SERVER_PRIMED)
|
||||
|
||||
var/tgs4_secret_sleep_offline_sauce = 24051994
|
||||
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)
|
||||
var/list/params = params2list(T)
|
||||
var/their_sCK = params[TGS4_INTEROP_ACCESS_IDENTIFIER]
|
||||
if(!their_sCK)
|
||||
return FALSE //continue world/Topic
|
||||
|
||||
if(their_sCK != access_identifier)
|
||||
return "Invalid comms key!";
|
||||
|
||||
var/command = params[TGS4_PARAMETER_COMMAND]
|
||||
if(!command)
|
||||
return "No command!"
|
||||
|
||||
. = TGS4_RESPONSE_SUCCESS
|
||||
|
||||
switch(command)
|
||||
if(TGS4_TOPIC_CHAT_COMMAND)
|
||||
var/result = HandleCustomCommand(params[TGS4_PARAMETER_DATA])
|
||||
if(result == null)
|
||||
result = "Error running chat command!"
|
||||
return result
|
||||
if(TGS4_TOPIC_EVENT)
|
||||
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"])
|
||||
if(event_parameters)
|
||||
event_call += event_parameters
|
||||
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(arglist(event_call))
|
||||
|
||||
. = json_encode(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])
|
||||
if (!(new_port > 0))
|
||||
return "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])
|
||||
if(event_handler != null)
|
||||
event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode)
|
||||
reboot_mode = new_reboot_mode
|
||||
return
|
||||
|
||||
return "Unknown command: [command]"
|
||||
|
||||
/datum/tgs_api/v4/proc/Export(command, list/data, override_requesting_new_port = FALSE)
|
||||
if(!data)
|
||||
data = list()
|
||||
data[TGS4_PARAMETER_COMMAND] = command
|
||||
var/json = json_encode(data)
|
||||
|
||||
while(requesting_new_port && !override_requesting_new_port)
|
||||
sleep(1)
|
||||
|
||||
//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)
|
||||
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]
|
||||
if(!isnum(port))
|
||||
return //this is valid, server may just want use to reboot
|
||||
|
||||
if(port == 0)
|
||||
//to byond 0 means any port and "none" means close vOv
|
||||
port = "none"
|
||||
|
||||
if(!world.OpenPort(port))
|
||||
TGS_ERROR_LOG("Unable to set port to [port]!")
|
||||
|
||||
/datum/tgs_api/v4/InstanceName()
|
||||
return instance_name
|
||||
|
||||
/datum/tgs_api/v4/TestMerges()
|
||||
return cached_test_merges
|
||||
|
||||
/datum/tgs_api/v4/EndProcess()
|
||||
Export(TGS4_COMM_END_PROCESS)
|
||||
|
||||
/datum/tgs_api/v4/Revision()
|
||||
return cached_revision
|
||||
|
||||
/datum/tgs_api/v4/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)
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Export(TGS4_COMM_CHAT, message)
|
||||
|
||||
/datum/tgs_api/v4/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)
|
||||
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))
|
||||
if(intercepted_message_queue)
|
||||
intercepted_message_queue += list(message)
|
||||
else
|
||||
Export(TGS4_COMM_CHAT, message)
|
||||
|
||||
/datum/tgs_api/v4/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)
|
||||
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"]
|
||||
return channel
|
||||
|
||||
/datum/tgs_api/v4/SecurityLevel()
|
||||
return security_level
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
69
code/modules/DMAPI/tgs/v4/commands.dm
Normal file
69
code/modules/DMAPI/tgs/v4/commands.dm
Normal file
@@ -0,0 +1,69 @@
|
||||
/datum/tgs_api/v4/proc/ListCustomCommands()
|
||||
var/results = list()
|
||||
custom_commands = list()
|
||||
for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command)
|
||||
var/datum/tgs_chat_command/stc = new I
|
||||
var/command_name = stc.name
|
||||
if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\""))
|
||||
TGS_ERROR_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!")
|
||||
continue
|
||||
|
||||
if(results[command_name])
|
||||
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))
|
||||
custom_commands[command_name] = stc
|
||||
|
||||
var/commands_file = chat_commands_json_path
|
||||
if(!commands_file)
|
||||
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"]
|
||||
|
||||
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"])
|
||||
|
||||
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]!"
|
||||
|
||||
/*
|
||||
|
||||
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.
|
||||
*/
|
||||
@@ -1,20 +1,30 @@
|
||||
/datum/server_tools_command/status
|
||||
|
||||
|
||||
var/global/client_count = 0
|
||||
|
||||
/client/New()
|
||||
..()
|
||||
++global.client_count
|
||||
|
||||
/client/Del()
|
||||
..()
|
||||
--global.client_count
|
||||
|
||||
/datum/tgs_chat_command/status
|
||||
name = "status" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command
|
||||
help_text = "Will broadcast the current player count and other round information" //help text for this command
|
||||
required_parameters = 0 //number of parameters required for this command
|
||||
admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins
|
||||
|
||||
/datum/server_tools_command/status/Run(sender, params)
|
||||
/datum/tgs_chat_command/status/Run(datum/tgs_chat_user/sender, params)
|
||||
return "```PLAYERCOUNT: [SERVER_TOOLS_CLIENT_COUNT] ROUND DURATION: [roundduration2text()]```"
|
||||
|
||||
// - FAX
|
||||
/datum/server_tools_command/readfax
|
||||
/datum/tgs_chat_command/readfax
|
||||
name = "readfax"
|
||||
help_text = "Reads a fax with specified faxid"
|
||||
required_parameters = 1
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/server_tools_command/readfax/Run(sender, params)
|
||||
/datum/tgs_chat_command/readfax/Run(datum/tgs_chat_user/sender, params)
|
||||
var/list/all_params = splittext(params, " ")
|
||||
var/faxid = all_params[1]
|
||||
var/faxmsg = return_file_text("[config.fax_export_dir]/fax_[faxid].html")
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "code\__defines\_globals.dm"
|
||||
#include "code\__defines\_planes+layers.dm"
|
||||
#include "code\__defines\_planes+layers_vr.dm"
|
||||
#include "code\__defines\_tgs.dm"
|
||||
#include "code\__defines\_tick.dm"
|
||||
#include "code\__defines\admin.dm"
|
||||
#include "code\__defines\admin_vr.dm"
|
||||
@@ -63,7 +64,6 @@
|
||||
#include "code\__defines\research.dm"
|
||||
#include "code\__defines\roguemining_vr.dm"
|
||||
#include "code\__defines\server_tools.config.dm"
|
||||
#include "code\__defines\server_tools.dm"
|
||||
#include "code\__defines\sound.dm"
|
||||
#include "code\__defines\species_languages.dm"
|
||||
#include "code\__defines\species_languages_vr.dm"
|
||||
@@ -1695,9 +1695,14 @@
|
||||
#include "code\modules\detectivework\tools\storage.dm"
|
||||
#include "code\modules\detectivework\tools\swabs.dm"
|
||||
#include "code\modules\detectivework\tools\uvlight.dm"
|
||||
#include "code\modules\DMAPI\st_commands.dm"
|
||||
#include "code\modules\DMAPI\st_interface.dm"
|
||||
#include "code\modules\DMAPI\yawnDMAPI.dm"
|
||||
#include "code\modules\DMAPI\tgs\includes.dm"
|
||||
#include "code\modules\DMAPI\tgs\core\_definitions.dm"
|
||||
#include "code\modules\DMAPI\tgs\core\core.dm"
|
||||
#include "code\modules\DMAPI\tgs\core\datum.dm"
|
||||
#include "code\modules\DMAPI\tgs\core\tgs_version.dm"
|
||||
#include "code\modules\DMAPI\tgs\v4\api.dm"
|
||||
#include "code\modules\DMAPI\tgs\v4\commands.dm"
|
||||
#include "code\modules\economy\Accounts.dm"
|
||||
#include "code\modules\economy\Accounts_DB.dm"
|
||||
#include "code\modules\economy\ATM.dm"
|
||||
|
||||
Reference in New Issue
Block a user