mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
[Manual MIRROR] dmapi manual update port (#11138)
This commit is contained in:
@@ -14,12 +14,9 @@
|
||||
|
||||
#include "v5\_defines.dm"
|
||||
#include "v5\api.dm"
|
||||
#include "v5\api_vgs.dm" //VOREStation Edit - Vgs
|
||||
#include "v5\bridge.dm"
|
||||
#include "v5\chunking.dm"
|
||||
#include "v5\commands.dm"
|
||||
#include "v5\chat_commands.dm" //CHOMPEdit
|
||||
#include "v5\chat_commands_zz_ch.dm" //CHOMPEdit
|
||||
#include "v5\serializers.dm"
|
||||
#include "v5\topic.dm"
|
||||
#include "v5\undefs.dm"
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5
|
||||
#define DMAPI5_BRIDGE_COMMAND_CHUNK 6
|
||||
#define DMAPI5_BRIDGE_COMMAND_EVENT 7
|
||||
#define DMAPI5_BRIDGE_COMMAND_ADD_MEMBER_ROLE 51 // VOREStation Edit
|
||||
|
||||
#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier"
|
||||
#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands"
|
||||
@@ -37,7 +36,6 @@
|
||||
#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_PARAMETER_CHAT_USER_ID "chatUserId" // VOREStation Edit
|
||||
|
||||
#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort"
|
||||
#define DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION "runtimeInformation"
|
||||
@@ -86,7 +84,6 @@
|
||||
#define DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK 10
|
||||
#define DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST 11
|
||||
#define DMAPI5_TOPIC_COMMAND_COMPLETE_EVENT 12
|
||||
#define DMAPI5_TOPIC_COMMAND_GET_CHAT_COMMANDS 51 // VOREStation Edit - GetChatCommands command
|
||||
|
||||
#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType"
|
||||
#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand"
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
// We currently isolate ourselves in a different variable so that only the specific APIs we choose will be active.
|
||||
// Eventually it would be good to handle all the TGS Apis properly and we can use the same.
|
||||
GLOBAL_DATUM(vgs, /datum/tgs_api)
|
||||
|
||||
// Supply our own New functionality so we can read from config instead of world params
|
||||
/world/proc/VgsNew(datum/tgs_event_handler/event_handler)
|
||||
var/current_api = GLOB.vgs
|
||||
if(current_api)
|
||||
TGS_ERROR_LOG("API datum already set (\ref[current_api] ([current_api]))! Was TgsNew() called more than once?")
|
||||
return
|
||||
|
||||
// If we don't have a configured access identifier we aren't meant to use VGS
|
||||
if(!CONFIG_GET(string/vgs_access_identifier))
|
||||
TGS_INFO_LOG("Skipping VGS: No access identifier configured")
|
||||
return
|
||||
|
||||
var/datum/tgs_api/api_datum = /datum/tgs_api/v5/vgs1
|
||||
TGS_INFO_LOG("Activating API for version [api_datum]")
|
||||
|
||||
if(event_handler && !istype(event_handler))
|
||||
TGS_ERROR_LOG("Invalid parameter for event_handler: [event_handler]")
|
||||
event_handler = null
|
||||
|
||||
var/datum/tgs_api/new_api = new api_datum(event_handler)
|
||||
GLOB.vgs = new_api
|
||||
|
||||
var/result = new_api.OnWorldNew()
|
||||
if(!result || result == TGS_UNIMPLEMENTED)
|
||||
GLOB.vgs = null
|
||||
TGS_ERROR_LOG("Failed to activate API!")
|
||||
|
||||
/world/proc/VgsTopic(T)
|
||||
var/datum/tgs_api/api = GLOB.vgs
|
||||
if(api)
|
||||
var/result = api.OnTopic(T)
|
||||
if(result != TGS_UNIMPLEMENTED)
|
||||
return result
|
||||
|
||||
/world/TgsReboot()
|
||||
var/datum/tgs_api/api = GLOB.vgs
|
||||
if(api)
|
||||
api.OnReboot()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/world/TgsInitializationComplete()
|
||||
var/datum/tgs_api/api = GLOB.vgs
|
||||
if(api)
|
||||
api.OnInitializationComplete()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/world/proc/VgsAddMemberRole(chat_user_id)
|
||||
var/datum/tgs_api/v5/vgs1/api = GLOB.vgs
|
||||
if(api)
|
||||
api.AddMemberRole(chat_user_id)
|
||||
|
||||
/datum/tgs_api/v5/vgs1
|
||||
server_port = 8080 // Default port
|
||||
|
||||
// Override to prevent error messages from the lack of revision/test_merge information, and to use config isntead of params.
|
||||
/datum/tgs_api/v5/vgs1/OnWorldNew()
|
||||
if(CONFIG_GET(number/vgs_server_port))
|
||||
server_port = CONFIG_GET(number/vgs_server_port)
|
||||
access_identifier = CONFIG_GET(string/vgs_access_identifier)
|
||||
|
||||
var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) //CHOMPEdit TGS update
|
||||
if(!istype(bridge_response))
|
||||
TGS_ERROR_LOG("Failed initial bridge request!")
|
||||
return FALSE
|
||||
|
||||
var/list/runtime_information = bridge_response[DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION]
|
||||
if(!istype(runtime_information))
|
||||
TGS_ERROR_LOG("Failed to decode runtime information from bridge response: [json_encode(bridge_response)]!")
|
||||
return FALSE
|
||||
|
||||
version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION])
|
||||
instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME]
|
||||
|
||||
chat_channels = list()
|
||||
DecodeChannels(runtime_information)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/tgs_api/v5/vgs1/proc/AddMemberRole(chat_user_id)
|
||||
Bridge(DMAPI5_BRIDGE_COMMAND_ADD_MEMBER_ROLE, list(DMAPI5_BRIDGE_PARAMETER_CHAT_USER_ID = chat_user_id))
|
||||
|
||||
// /datum/tgs_api/v5/vgs1/RequireInitialBridgeResponse()
|
||||
// while(!instance_name)
|
||||
// sleep(1)
|
||||
@@ -1,160 +0,0 @@
|
||||
/datum/tgs_chat_command/status
|
||||
name = "status"
|
||||
help_text = "Shows the current production server status"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/status/Run(datum/tgs_chat_user/sender, params)
|
||||
var/counts = 0
|
||||
var/afks = 0
|
||||
var/active = 0
|
||||
var/bellied = 0
|
||||
// var/map_name = "n/a" //CHOMP Remove we don't use this and it is causing problems with the dmb compiler.
|
||||
// if(using_map && using_map.full_name)
|
||||
// map_name = using_map.full_name
|
||||
|
||||
for(var/X in GLOB.clients)
|
||||
var/client/C = X
|
||||
if(C)
|
||||
counts++
|
||||
if(!(isnewplayer(C.mob) || istype(C.mob, /mob/observer)))
|
||||
if(C.mob && isbelly(C.mob.loc))
|
||||
bellied++
|
||||
if(C.is_afk())
|
||||
afks++
|
||||
else
|
||||
active++
|
||||
|
||||
return "Current server status:\n**Web Manifest:** <http://manifest.chompstation13.net/>\n**Players:** [counts]\n**Active:** [active]\n**Bar Statues:** [afks]\n**Bellied:** [bellied]\n\n**Round Duration:** [roundduration2text()]" //CHOMPEdit
|
||||
|
||||
/datum/tgs_chat_command/parsetest
|
||||
name = "parsetest"
|
||||
help_text = "Shows the current production server status"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/parsetest/Run(datum/tgs_chat_user/sender, params)
|
||||
return "```You passed:[params]```"
|
||||
|
||||
/datum/tgs_chat_command/staffwho
|
||||
name = "staffwho"
|
||||
help_text = "Shows the current online staff count"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/staffwho/Run(datum/tgs_chat_user/sender, params)
|
||||
var/message = "Current online staff:\n"
|
||||
|
||||
var/list/admin_keys = list()
|
||||
var/list/mod_keys = list()
|
||||
var/list/dev_keys = list()
|
||||
var/list/other_keys = list()
|
||||
|
||||
var/count = 0
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
count++
|
||||
var/keymsg = "[C.key]"
|
||||
if(C.is_afk())
|
||||
keymsg += " (AFK)"
|
||||
else if(C.holder.fakekey)
|
||||
keymsg += " (Stealth)"
|
||||
else if(isobserver(C.mob))
|
||||
keymsg += " (Ghost)"
|
||||
else if(isnewplayer(C.mob))
|
||||
keymsg += " (Lobby)"
|
||||
else
|
||||
keymsg += " (Ingame)"
|
||||
|
||||
if(check_rights_for(C, R_ADMIN) && check_rights_for(C, R_BAN)) // R_ADMIN and R_BAN apparently an admin makes
|
||||
admin_keys += keymsg
|
||||
|
||||
else if(check_rights_for(C, R_ADMIN) && !(check_rights_for(C, R_SERVER))) // R_ADMIN but not R_SERVER makes a moderator
|
||||
mod_keys += keymsg
|
||||
|
||||
else if(check_rights_for(C, R_SERVER)) // R_SERVER makes a dev
|
||||
dev_keys += keymsg
|
||||
|
||||
else // No R_ADMIN&&R_BAN, R_ADMIN!R_BAN, R_SERVER, must be a GM or something
|
||||
other_keys += keymsg
|
||||
|
||||
var/admin_msg = english_list(admin_keys, "-None-")
|
||||
var/mod_msg = english_list(mod_keys, "-None-")
|
||||
var/dev_msg = english_list(dev_keys, "-None-")
|
||||
var/other_msg = english_list(other_keys, "-None-")
|
||||
|
||||
message += "**Admins:** [admin_msg]\n**Mods/GMs:** [mod_msg]\n**Devs:** [dev_msg]\n**Other:** [other_msg]\n**Total:** [count] online"
|
||||
return message
|
||||
|
||||
GLOBAL_LIST_EMPTY(pending_discord_registrations)
|
||||
/datum/tgs_chat_command/register
|
||||
name = "register"
|
||||
help_text = "Registers your chat username with your Byond username"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/register/Run(datum/tgs_chat_user/sender, params)
|
||||
// Try to find if that ID is registered to someone already
|
||||
var/sql_discord = sql_sanitize_text(sender.id)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT discord_id FROM erro_player WHERE discord_id = '[sql_discord]'")
|
||||
query.Execute()
|
||||
if(query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], your Discord ID is already registered to a Byond username. Please contact an administrator if you changed your Byond username or Discord ID."
|
||||
qdel(query)
|
||||
var/key_to_find = "[ckey(params)]"
|
||||
|
||||
// They didn't provide anything worth looking up.
|
||||
if(!length(key_to_find))
|
||||
return "[sender.friendly_name], you need to provide your Byond username at the end of the command. It can be in 'key' format (with spaces and characters) or 'ckey' format (without spaces or special characters)."
|
||||
|
||||
// Try to find their client.
|
||||
var/client/user
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(C.ckey == key_to_find)
|
||||
user = C
|
||||
break
|
||||
|
||||
// Couldn't find them logged in.
|
||||
if(!user)
|
||||
return "[sender.friendly_name], I couldn't find a logged-in user with the username of '[key_to_find]', which is what you provided after conversion to Byond's ckey format. Please connect to the game server and try again."
|
||||
|
||||
var/sql_ckey = sql_sanitize_text(key_to_find)
|
||||
query = SSdbcore.NewQuery("SELECT discord_id FROM erro_player WHERE ckey = '[sql_ckey]'")
|
||||
query.Execute()
|
||||
|
||||
// We somehow found their client, BUT they don't exist in the database
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no evidence you've ever logged in. Please contact an administrator."
|
||||
|
||||
// We found them in the database, AND they already have a discord ID assigned
|
||||
if(query.item[1])
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], it appears you've already registered your chat and game IDs. If you've changed game or chat usernames, please contact an administrator for help."
|
||||
qdel(query)
|
||||
// Okay. We found them, they're in the DB, and they have no discord ID set.
|
||||
var/message = span_notice("A request has been sent from Discord to validate your Byond username, by '[sender.friendly_name]' in '[sender.channel.friendly_name]'") + "\
|
||||
<br>" + span_warning("If you did not send this request, do not click the link below, and do notify an administrator in-game or on Discord ASAP.") + "\
|
||||
<br><a href='byond://?src=\ref[user];discord_reg=[html_encode(sender.id)]'>Click Here</a> if you authorized this registration attempt. This link is valid for 10 minutes."
|
||||
to_chat(user, message)
|
||||
|
||||
// To stifle href hacking
|
||||
GLOB.pending_discord_registrations.len++
|
||||
GLOB.pending_discord_registrations[GLOB.pending_discord_registrations.len] = list("ckey" = key_to_find, "id" = sender.id, "time" = world.realtime)
|
||||
|
||||
return "[sender.friendly_name], I've sent you a message in-game. Please verify your username there to complete your registration within 10 minutes."
|
||||
|
||||
/*//YW Commands //CHOMP Commenting this out for now. Should now be using Virgo's version.
|
||||
//Status
|
||||
/datum/tgs_chat_command/status/Run(datum/tgs_chat_user/sender, params)
|
||||
return "Current server status:**Players:** [TGS_CLIENT_COUNT]\n**Round Duration:** [roundduration2text()]"
|
||||
*/
|
||||
// - FAX
|
||||
/datum/tgs_chat_command/readfax
|
||||
name = "readfax"
|
||||
help_text = "Reads a fax with specified faxid"
|
||||
//required_parameters = 1 Is not a thing
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/readfax/Run(sender, params)
|
||||
var/list/all_params = splittext(params, " ")
|
||||
var/faxid = all_params[1]
|
||||
var/faxmsg = return_file_text("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html") // CHOMPEdit
|
||||
return "FAX: ```[strip_html_properly(faxmsg)]```"
|
||||
@@ -1,118 +0,0 @@
|
||||
/datum/tgs_chat_command/sharktest
|
||||
name = "flip"
|
||||
help_text = "babies first TGS command"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/sharktest/Run(datum/tgs_chat_user/sender, params)
|
||||
var/x
|
||||
if(params != "tails" && params != "heads")
|
||||
return "```You need to guess!\n either heads or tails!```"
|
||||
if(prob(50))
|
||||
if(params == "tails")
|
||||
x = "correct"
|
||||
else
|
||||
x = "wrong"
|
||||
return "```Tails. [x]!```"
|
||||
|
||||
if(params == "tails")
|
||||
x = "wrong"
|
||||
else
|
||||
x = "correct"
|
||||
return "```Heads. [x]!```"
|
||||
|
||||
/datum/tgs_chat_command/sharktest/alias
|
||||
name = "coin"
|
||||
|
||||
/datum/tgs_chat_command/manifest
|
||||
name = "manifest"
|
||||
help_text = "Shows the current crew manifest"
|
||||
admin_only = FALSE
|
||||
|
||||
/proc/ManifestToHtml()
|
||||
var/html = ""
|
||||
if(GLOB.data_core)
|
||||
html = GLOB.data_core.get_manifest(FALSE,TRUE,snowflake = TRUE)
|
||||
else
|
||||
html = span_bold("ERROR: NO DATACORE") //Could make the error more fancy later
|
||||
rustg_file_write(html,"[CONFIG_GET(string/nodebot_location)]\\html.html")
|
||||
|
||||
/datum/tgs_chat_command/manifest/Run(datum/tgs_chat_user/sender, params)
|
||||
if(CONFIG_GET(flag/nodebot_enabled))
|
||||
ManifestToHtml()
|
||||
return "http://manifest.chompstation13.net/"
|
||||
else
|
||||
var/outp = "Crew Manifest:"
|
||||
var/list/total = list()
|
||||
if(GLOB.data_core)
|
||||
GLOB.data_core.get_manifest_list()
|
||||
for(var/list/item in GLOB.PDA_Manifest)
|
||||
outp += "\n__**[item["cat"]]:**__"
|
||||
for(var/list/person in item["elems"])
|
||||
total |= person
|
||||
outp += "\n[person["name"]] -:- [person["rank"]]"
|
||||
|
||||
return "**Total crew members:** [total.len]\n" + outp
|
||||
|
||||
|
||||
/datum/tgs_chat_command/discordping
|
||||
name = "discordping"
|
||||
help_text = "Pings the discord associated with the associated ckey"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/discordping/Run(datum/tgs_chat_user/sender, params)
|
||||
var/key_to_find = "[ckey(params)]"
|
||||
|
||||
// They didn't provide anything worth looking up.
|
||||
if(!length(key_to_find))
|
||||
return "[sender.friendly_name], you need to provide a Byond username at the end of the command. It can be in 'key' format (with spaces and characters) or 'ckey' format (without spaces or special characters)."
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT discord_id FROM erro_player WHERE ckey = :t_ckey",list("t_ckey" = key_to_find))
|
||||
query.Execute()
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no such ckey in the database."
|
||||
|
||||
if(!query.item[1])
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], [key_to_find] is in the database, but has no discord ID associated with them."
|
||||
var/discord_id = query.item[1]
|
||||
qdel(query)
|
||||
return "[key_to_find]'s discord is <@[discord_id]>"
|
||||
|
||||
/datum/tgs_chat_command/getkey
|
||||
name = "getkey"
|
||||
help_text = "Finds the key associated with a discord id"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/getkey/Run(datum/tgs_chat_user/sender, params)
|
||||
if(!params)
|
||||
return "[sender.friendly_name], you need to provide a Discord ID at the end of the command. To obtain someone's Discord ID, you need to enable developer mode on discord, and then right click on their name and click Copy ID."
|
||||
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE discord_id = :t_discord", list("t_discord"=params))
|
||||
query.Execute()
|
||||
|
||||
if(!query.NextRow())
|
||||
qdel(query)
|
||||
return "[sender.friendly_name], the server's database is either not responding or there's no such Discord ID in the database."
|
||||
|
||||
var/user_key = query.item[1]
|
||||
qdel(query)
|
||||
return "<@[params]>'s ckey is [user_key]"
|
||||
|
||||
//modded fax code to properly handle non existing files before accessing the void
|
||||
/datum/tgs_chat_command/readfax/Run(sender, params)
|
||||
var/list/all_params = splittext(params, " ")
|
||||
var/faxid = all_params[1]
|
||||
if(!all_params[1] || !fexists("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html"))
|
||||
return "I’m sorry Dave, I’m afraid I can’t do that"
|
||||
var/faxmsg = return_file_text("[CONFIG_GET(string/fax_export_dir)]/fax_[faxid].html")
|
||||
return "FAX: ```[strip_html_properly(faxmsg)]```"
|
||||
|
||||
/datum/tgs_chat_command/vore
|
||||
name = "vore"
|
||||
help_text = "vore"
|
||||
admin_only = FALSE
|
||||
|
||||
/datum/tgs_chat_command/vore/Run(datum/tgs_chat_user/sender, params)
|
||||
return "vore"
|
||||
@@ -60,12 +60,6 @@
|
||||
intercepted_message_queue = null
|
||||
return result
|
||||
|
||||
// VOREStation Edit Start - GetChatCommands command
|
||||
if(DMAPI5_TOPIC_COMMAND_GET_CHAT_COMMANDS)
|
||||
var/topic_response = list(DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())
|
||||
return json_encode(topic_response)
|
||||
// VOREStation Edit - End
|
||||
|
||||
if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION)
|
||||
var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]
|
||||
if(!istype(event_notification))
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND
|
||||
#undef DMAPI5_BRIDGE_COMMAND_CHUNK
|
||||
#undef DMAPI5_BRIDGE_COMMAND_EVENT
|
||||
#undef DMAPI5_BRIDGE_COMMAND_ADD_MEMBER_ROLE // VOREStation Edit
|
||||
|
||||
#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER
|
||||
#undef DMAPI5_PARAMETER_CUSTOM_COMMANDS
|
||||
@@ -37,7 +36,6 @@
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_EVENT_INVOCATION
|
||||
#undef DMAPI5_BRIDGE_PARAMETER_CHAT_USER_ID // VOREStation Edit
|
||||
|
||||
#undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT
|
||||
#undef DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION
|
||||
@@ -86,7 +84,6 @@
|
||||
#undef DMAPI5_TOPIC_COMMAND_RECEIVE_CHUNK
|
||||
#undef DMAPI5_TOPIC_COMMAND_RECEIVE_BROADCAST
|
||||
#undef DMAPI5_TOPIC_COMMAND_COMPLETE_EVENT
|
||||
#undef DMAPI5_TOPIC_COMMAND_GET_CHAT_COMMANDS // VOREStation Edit - Custom Commands
|
||||
|
||||
#undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE
|
||||
#undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND
|
||||
|
||||
Reference in New Issue
Block a user