[Manual MIRROR] dmapi manual update port (#11138)

This commit is contained in:
Kashargul
2025-07-03 23:30:00 +02:00
committed by GitHub
parent 7d7ef755ee
commit c71ab6c9bd
48 changed files with 1101 additions and 629 deletions
+28 -22
View File
@@ -2,33 +2,39 @@ name: TGS Test Suite
on:
push:
branches:
- master
- master
- "project/**"
- "gh-readonly-queue/master/**"
- "gh-readonly-queue/project/**"
paths:
- '.tgs.yml'
- '.github/workflows/tgs_test.yml'
- 'dependencies.sh'
- 'code/__DEFINES/tgs.config.dm'
- 'code/__DEFINES/tgs.dm'
- 'code/game/world.dm'
- 'code/modules/tgs/**'
- 'tools/tgs_scripts/**'
- 'tools/tgs_test/**'
- ".tgs.yml"
- ".github/workflows/tgs_test.yml"
- "dependencies.sh"
- "code/__DEFINES/tgs.config.dm"
- "code/__DEFINES/tgs.dm"
- "code/game/world.dm"
- "code/modules/tgs/**"
- "tools/bootstrap/**"
- "tools/tgs_scripts/**"
- "tools/tgs_test/**"
pull_request:
branches:
- master
- master
- "project/**"
paths:
- '.tgs.yml'
- '.github/workflows/tgs_test.yml'
- 'dependencies.sh'
- 'code/__DEFINES/tgs.config.dm'
- 'code/__DEFINES/tgs.dm'
- 'code/game/world.dm'
- 'code/modules/tgs/**'
- 'tools/tgs_scripts/**'
- 'tools/tgs_test/**'
- ".tgs.yml"
- ".github/workflows/tgs_test.yml"
- "dependencies.sh"
- "code/__DEFINES/tgs.config.dm"
- "code/__DEFINES/tgs.dm"
- "code/game/world.dm"
- "code/modules/tgs/**"
- "tools/bootstrap/**"
- "tools/tgs_scripts/**"
- "tools/tgs_test/**"
merge_group:
branches:
- master
- master
env:
TGS_API_PORT: 5000
PR_NUMBER: ${{ github.event.number }}
@@ -61,4 +67,4 @@ jobs:
uses: actions/checkout@v4
- name: Test TGS Integration
run: dotnet run -c Release --project tools/tgs_test ${{ github.repository }} /tgs_instances/chompstation ${{ env.TGS_API_PORT }} ${{ github.event.pull_request.head.sha || github.sha }} ${{ secrets.GITHUB_TOKEN }} ${{ env.PR_NUMBER }}
run: dotnet run -c Release --project tools/tgs_test ${{ github.repository }} /tgs_instances/tgstation ${{ env.TGS_API_PORT }} ${{ github.event.pull_request.head.sha || github.sha }} ${{ secrets.GITHUB_TOKEN }} ${{ env.PR_NUMBER }}
+47 -35
View File
@@ -2,47 +2,59 @@ name: Update TGS DMAPI
on:
schedule:
- cron: "0 0 1 */2 *"
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
update-dmapi:
runs-on: ubuntu-24.04
name: Updates the TGS DMAPI
name: Update the TGS DMAPI
permissions:
contents: write
pull-requests: write
steps:
- name: Clone
uses: actions/checkout@v4
- name: Clone
uses: actions/checkout@v4
- name: Branch
run: |
git branch -f tgs-dmapi-update
git checkout tgs-dmapi-update
git reset --hard master
- name: Branch
run: |
git branch -f tgs-dmapi-update
git checkout tgs-dmapi-update
git reset --hard master
- name: Apply DMAPI update
uses: tgstation/tgs-dmapi-updater@v2
id: dmapi-update
with:
header-path: "code/__defines/tgs.dm"
library-path: "code/modules/tgs"
- name: Apply DMAPI update
uses: tgstation/tgs-dmapi-updater@v2
id: dmapi-update
with:
header-path: 'code/__defines/tgs.dm'
library-path: 'code/modules/tgs'
- name: Commit and Push
continue-on-error: true
run: |
git config user.name "chompstation-ci[bot]"
git config user.email "12787406+chompstation-ci[bot]@users.noreply.github.com"
git add .
git commit -m 'Update TGS DMAPI'
git push -f -u origin tgs-dmapi-update
- name: Generate App Token
id: app-token-generation
uses: actions/create-github-app-token@v2
if: env.APP_PRIVATE_KEY != '' && env.APP_ID != ''
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
env:
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
APP_ID: ${{ secrets.APP_ID }}
- name: Commit and Push
continue-on-error: true
run: |
git config --local user.email "action@github.com"
git config --local user.name "DMAPI Update"
git add .
git commit -m 'Update TGS DMAPI'
git push -f -u origin tgs-dmapi-update
- name: Create Pull Request
uses: repo-sync/pull-request@v2
with:
source_branch: "tgs-dmapi-update"
destination_branch: "master"
pr_title: "Automatic DMAPI Update"
pr_body: "This pull request updates the DMAPI to the latest version."
pr_label: "Infrastructure"
pr_allow_empty: false
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Pull Request
uses: repo-sync/pull-request@v2
if: ${{ success() }}
with:
source_branch: "tgs-dmapi-update"
destination_branch: "master"
pr_title: "Automatic TGS DMAPI Update"
pr_body: "This pull request updates the TGS DMAPI to the latest version. Please note any changes that may be breaking or unimplemented in your codebase by checking what changes are in the definitions file: code/__DEFINES/tgs.dm before merging.\n\n${{ steps.dmapi-update.outputs.release-notes }}"
pr_label: "Tools"
pr_allow_empty: false
github_token: ${{ steps.app-token-generation.outputs.token || secrets.GITHUB_TOKEN }}
+7 -7
View File
@@ -3,7 +3,7 @@
"tasks": [
{
"type": "process",
"command": "tools/build/build",
"command": "tools/build/build.sh",
"windows": {
"command": ".\\tools\\build\\build.bat"
},
@@ -26,11 +26,11 @@
},
{
"type": "process",
"command": "tools/build/build",
"command": "tools/build/build.sh",
"args": ["-DLOWMEMORYMODE"],
"windows": {
"command": ".\\tools\\build\\build.bat",
"args": ["-DLOWMEMORYMODE", "-DENABLE_BYOND_TRACY"]
"args": ["-DLOWMEMORYMODE"]
},
"options": {
"env": {
@@ -50,7 +50,7 @@
},
{
"type": "process",
"command": "tools/build/build",
"command": "tools/build/build.sh",
"args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_TETHER"],
"windows": {
"command": ".\\tools\\build\\build.bat",
@@ -74,7 +74,7 @@
},
{
"type": "process",
"command": "tools/build/build",
"command": "tools/build/build.sh",
"args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_STELLARDELIGHT"],
"windows": {
"command": ".\\tools\\build\\build.bat",
@@ -98,7 +98,7 @@
},
{
"type": "process",
"command": "tools/build/build",
"command": "tools/build/build.sh",
"args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_GROUNDBASE"],
"windows": {
"command": ".\\tools\\build\\build.bat",
@@ -122,7 +122,7 @@
},
{
"type": "process",
"command": "tools/build/build",
"command": "tools/build/build.sh",
"args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_MINITEST"],
"windows": {
"command": ".\\tools\\build\\build.bat",
+9
View File
@@ -35,3 +35,12 @@
#define MESSAGE_TYPE_ADMINLOG "adminlog"
#define MESSAGE_TYPE_ATTACKLOG "attacklog"
#define MESSAGE_TYPE_DEBUG "debug"
/// Adds a generic box around whatever message you're sending in chat. Really makes things stand out.
#define boxed_message(str) ("<div class='boxed_message'>" + str + "</div>")
/// Adds a box around whatever message you're sending in chat. Can apply color and/or additional classes. Available colors: red, green, blue, purple. Use it like red_box
#define custom_boxed_message(classes, str) ("<div class='boxed_message " + classes + "'>" + str + "</div>")
/// Makes a fieldset with a neaty styled name. Can apply additional classes.
#define fieldset_block(title, content, classes) ("<fieldset class='fieldset " + classes + "'><legend class='fieldset_legend'>" + title + "</legend>" + content + "</fieldset>")
/// Makes a horizontal line with text in the middle
#define separator_hr(str) ("<div class='separator'>" + str + "</div>")
+1 -2
View File
@@ -164,7 +164,7 @@
* * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED].
* * http_handler - Optional user defined [/datum/tgs_http_handler].
*/
/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_TRUSTED, datum/tgs_http_handler/http_handler) //CHOMPEdit we need trusted
/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE, datum/tgs_http_handler/http_handler)
CAN_BE_REDEFINED(TRUE)
return
@@ -181,7 +181,6 @@
/// Consumers MUST run this macro at the start of [/world/proc/Topic].
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return
#define VGS_TOPIC var/vgs_topic_return = VgsTopic(args[1]); if(vgs_topic_return) return vgs_topic_return // VOREStation Edit - VGS
/// Consumers MUST call this as late as possible in [world/proc/Reboot] (BEFORE ..()).
/world/proc/TgsReboot()
@@ -747,3 +747,7 @@
/// Turn this on if you want all admin-PMs to go to be sent to discord, and not only the first message of a ticket.
/datum/config_entry/flag/discord_ahelps_all
default = FALSE
/datum/config_entry/number/rounds_until_hard_restart
default = -1
min_val = 0
@@ -2,11 +2,7 @@
/datum/config_entry/flag/items_survive_digestion
default = TRUE
/datum/config_entry/string/vgs_access_identifier // VGS
default = null
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
/datum/config_entry/number/vgs_server_port // VGS
/datum/config_entry/number/register_server_port
default = null
min_val = 0
max_val = 65535
+1 -1
View File
@@ -152,7 +152,7 @@
// we are wearing shoes
var/obj/item/clothing/shoes/feet = source.shoes
if(feet.blocks_footsteps)
if(istype(feet) && feet.blocks_footsteps)
var/shoestep_type = prepared_steps[FOOTSTEP_MOB_SHOE]
if(!isnull(shoestep_type) && footstep_sounds[shoestep_type]) // shoestep type can be null
playsound(source.loc, pick(footstep_sounds[shoestep_type][1]),
+67 -58
View File
@@ -1,82 +1,91 @@
/datum/getrev
var/branch
var/revision
var/commit // git rev-parse HEAD
var/date
var/showinfo
var/originmastercommit // git rev-parse origin/master
var/list/testmerge = list()
/datum/getrev/New()
if(world.TgsAvailable()) // Try TGS maybe
testmerge = world.TgsTestMerges()
var/datum/tgs_revision_information/REV = world.TgsRevision()
if(REV)
revision = REV.origin_commit || REV.commit
branch = "-Using TGS-" // TGS doesn't provide branch info yet
date = "-Using TGS-" // Or date
commit = rustg_git_revparse("HEAD")
if(commit)
date = rustg_git_commit_date(commit)
originmastercommit = rustg_git_revparse("origin/master")
if(!revision) // File parse method
var/list/head_branch = file2list(".git/HEAD", "\n")
if(head_branch.len)
branch = copytext(head_branch[1], 17)
/datum/getrev/proc/load_tgs_info()
testmerge = world.TgsTestMerges()
var/datum/tgs_revision_information/revinfo = world.TgsRevision()
if(revinfo)
commit = revinfo.commit
originmastercommit = revinfo.origin_commit
date = revinfo.timestamp || rustg_git_commit_date(commit)
var/list/head_log = file2list(".git/logs/HEAD", "\n")
for(var/line=head_log.len, line>=1, line--)
if(head_log[line])
var/list/last_entry = splittext(head_log[line], " ")
if(last_entry.len < 2) continue
revision = last_entry[2]
// Get date/time
if(last_entry.len >= 5)
var/unix_time = text2num(last_entry[5])
if(unix_time)
date = unix2date(unix_time)
break
// goes to DD log and config_error.txt
log_world(get_log_message())
to_world_log("-Revision Info-")
to_world_log("Branch: [branch]")
to_world_log("Date: [date]")
to_world_log("Revision: [revision]")
/datum/getrev/proc/get_log_message()
var/list/msg = list()
msg += "Running /tg/ revision: [date]"
if(originmastercommit)
msg += "origin/master: [originmastercommit]"
for(var/line in testmerge)
var/datum/tgs_revision_information/test_merge/tm = line
msg += "Test merge active of PR #[tm.number] commit [tm.head_commit]"
//SSblackbox.record_feedback("associative", "testmerged_prs", 1, list("number" = "[tm.number]", "commit" = "[tm.head_commit]", "title" = "[tm.title]", "author" = "[tm.author]"))
if(commit && commit != originmastercommit)
msg += "HEAD: [commit]"
else if(!originmastercommit)
msg += "No commit information"
msg += "Running rust-g version [rustg_get_version()]"
return msg.Join("\n")
/datum/getrev/proc/GetTestMergeInfo(header = TRUE)
. = list()
if(!testmerge.len)
return
if(header)
. += "The following pull requests are currently test merged:"
for(var/datum/tgs_revision_information/test_merge/tm as anything in testmerge)
var/cm = tm.head_commit //CHOMPStation Edit TGS4
return ""
. = header ? "The following pull requests are currently test merged:<br>" : ""
for(var/line in testmerge)
var/datum/tgs_revision_information/test_merge/tm = line
var/cm = tm.head_commit
var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext_char(cm, 1, 11))
if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder))
continue
. += "<a href=\"[CONFIG_GET(string/githuburl)]/pull/[tm.number]\">#[tm.number][details]</a>"
. += "<a href=\"[CONFIG_GET(string/githuburl)]/pull/[tm.number]\">#[tm.number][details]</a><br>"
/client/verb/showrevinfo()
set category = "OOC.Game"
set name = "Show Server Revision"
set desc = "Check the current server code revision"
if(!GLOB.revdata)
to_chat(src, span_warning("Please wait until server initializations are complete."))
return
var/list/msg = list()
// Round ID
if(GLOB.round_id)
msg += span_bold("Round ID") + ": [GLOB.round_id]"
if(GLOB.revdata.revision)
msg += span_bold("Server revision:") + " B:[GLOB.revdata.branch] D:[GLOB.revdata.date]"
if(CONFIG_GET(string/githuburl))
msg += span_bold("Commit:") + " <a href='[CONFIG_GET(string/githuburl)]/commit/[GLOB.revdata.revision]'>[GLOB.revdata.revision]</a>"
else
msg += span_bold("Commit:") + " [GLOB.revdata.revision]" // CHOMPEdit - Actually SHOW the revision
else
msg += span_bold("Server revision:") + " Unknown"
msg += span_bold("BYOND Version") + ": [world.byond_version].[world.byond_build]"
if(DM_VERSION != world.byond_version || DM_BUILD != world.byond_build)
msg += span_bold("Compiled with BYOND Version") + ": [DM_VERSION].[DM_BUILD]"
// Revision information
var/datum/getrev/revdata = GLOB.revdata
msg += span_bold("Server revision compiled on") + ": [revdata.date]"
var/pc = revdata.originmastercommit
if(pc)
msg += span_bold("Master commit") + ": <a href=\"[CONFIG_GET(string/githuburl)]/commit/[pc]\">[pc]</a>"
if(length(revdata.testmerge))
msg += revdata.GetTestMergeInfo()
if(revdata.commit && revdata.commit != revdata.originmastercommit)
msg += span_bold("Local commit") + ": [revdata.commit]"
else if(!pc)
msg += "No commit information"
if(world.TgsAvailable())
var/datum/tgs_version/version = world.TgsVersion()
msg += span_bold("TGS version:") + " [version.raw_parameter]"
var/datum/tgs_version/api_version = world.TgsApiVersion()
msg += span_bold("DMAPI version:") + " [api_version.raw_parameter]"
msg += span_bold("TGS version") + ": [version.raw_parameter]"
msg += span_bold("DMAPI version") + ": [TGS_DMAPI_VERSION]"
if(GLOB.revdata.testmerge.len)
msg += GLOB.revdata.GetTestMergeInfo()
to_chat(src, msg.Join("<br>"))
// Game mode odds
//msg += "<br><b>Current Informational Settings:</b>"
//msg += "<b>Protect Authority Roles From Traitor:</b> [CONFIG_GET(flag/protect_roles_from_antagonist) ? "Yes" : "No"]"
//msg += "<b>Protect Assistant Role From Traitor:</b> [CONFIG_GET(flag/protect_assistant_from_antagonist) ? "Yes" : "No"]"
//msg += "<b>Enforce Human Authority:</b> [CONFIG_GET(string/human_authority) ? "Yes" : "No"]"
//msg += "<b>Allow Latejoin Antagonists:</b> [CONFIG_GET(flag/allow_latejoin_antagonists) ? "Yes" : "No"]"
to_chat(src, fieldset_block("Server Revision Info", span_infoplain(jointext(msg, "<br>")), "boxed_message"), type = MESSAGE_TYPE_INFO)
+46 -6
View File
@@ -1,3 +1,7 @@
#define RESTART_COUNTER_PATH "data/round_counter.txt"
GLOBAL_VAR(restart_counter)
#define RECOMMENDED_VERSION 513
/world/New()
world_startup_time = world.timeofday
@@ -32,7 +36,7 @@
if(byond_version < RECOMMENDED_VERSION)
to_world_log("Your server's byond version does not meet the recommended requirements for this server. Please update BYOND")
TgsNew(new /datum/tgs_event_handler/impl, TGS_SECURITY_TRUSTED) // CHOMPEdit - tgs event handler
InitTgs()
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
@@ -40,7 +44,6 @@
ConfigLoaded()
makeDatumRefLists()
VgsNew()
var servername = CONFIG_GET(string/servername)
if(config && servername != null && CONFIG_GET(flag/server_suffix) && world.port > 0)
@@ -103,6 +106,11 @@
return
/// Initializes TGS and loads the returned revising info into GLOB.revdata
/world/proc/InitTgs()
TgsNew(new /datum/tgs_event_handler/impl, TGS_SECURITY_TRUSTED)
GLOB.revdata.load_tgs_info()
/// Runs after config is loaded but before Master is initialized
/world/proc/ConfigLoaded()
// Everything in here is prioritized in a very specific way.
@@ -119,12 +127,15 @@
else //probably windows, if not this should work anyway
CONFIG_SET(string/python_path, "python")
if(fexists(RESTART_COUNTER_PATH))
GLOB.restart_counter = text2num(trim(file2text(RESTART_COUNTER_PATH)))
fdel(RESTART_COUNTER_PATH)
var/world_topic_spam_protect_ip = "0.0.0.0"
var/world_topic_spam_protect_time = world.timeofday
/world/Topic(T, addr, master, key)
VGS_TOPIC // VOREStation Edit - VGS //CHOMP Edit swapped lines around
TGS_TOPIC //CHOMP Edit swapped lines around
TGS_TOPIC
log_topic("\"[T]\", from:[addr], master:[master], key:[key]")
if (T == "ping")
@@ -275,8 +286,8 @@ var/world_topic_spam_protect_time = world.timeofday
return list2params(positions)
else if(T == "revision")
if(GLOB.revdata.revision)
return list2params(list(branch = GLOB.revdata.branch, date = GLOB.revdata.date, revision = GLOB.revdata.revision))
if(GLOB.revdata.commit)
return list2params(list(testmerge = GLOB.revdata.testmerge, date = GLOB.revdata.date, commit = GLOB.revdata.commit, originmastercommit = GLOB.revdata.originmastercommit))
else
return "unknown"
@@ -457,6 +468,25 @@ var/world_topic_spam_protect_time = world.timeofday
else
return "Database connection failed or not set up"
/// Returns TRUE if the world should do a TGS hard reboot.
/world/proc/check_hard_reboot()
if(!TgsAvailable())
return FALSE
// byond-tracy can't clean up itself, and thus we should always hard reboot if its enabled, to avoid an infinitely growing trace.
//if(Tracy?.enabled)
// return TRUE
var/ruhr = CONFIG_GET(number/rounds_until_hard_restart)
switch(ruhr)
if(-1)
return FALSE
if(0)
return TRUE
else
if(GLOB.restart_counter >= ruhr)
return TRUE
else
text2file("[++GLOB.restart_counter]", RESTART_COUNTER_PATH)
return FALSE
/world/Reboot(reason = 0, fast_track = FALSE)
/*spawn(0)
@@ -477,6 +507,14 @@ var/world_topic_spam_protect_time = world.timeofday
if(CONFIG_GET(string/server)) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[CONFIG_GET(string/server)]")
if(check_hard_reboot())
log_world("World hard rebooted at [time_stamp()]")
//shutdown_logging() // See comment below.
//QDEL_NULL(Tracy)
//QDEL_NULL(Debugger)
TgsEndProcess()
return ..()
TgsReboot()
log_world("World rebooted at [time_stamp()]")
..()
@@ -774,3 +812,5 @@ var/global/game_id = null
if (debug_server)
call_ext(debug_server, "auxtools_shutdown")()
. = ..()
#undef RESTART_COUNTER_PATH
+8
View File
@@ -455,7 +455,13 @@ ADMIN_VERB(edit_admin_permissions, R_PERMISSIONS, "Permissions Panel", "Edit adm
#undef RANK_DONE
/// Changes, for this round only, the flags a particular admin gets to use
/datum/admins/proc/change_admin_flags(admin_ckey, admin_key, datum/admins/admin_holder)
if(!check_rights(R_PERMISSIONS))
return
if(IsAdminAdvancedProcCall())
to_chat(usr, span_adminprefix("Rank Modification blocked: Advanced ProcCall detected."), confidential = TRUE)
return
var/new_flags = input_bitfield(
usr,
"Admin rights<br>This will affect only the current admin [admin_key]",
@@ -465,6 +471,8 @@ ADMIN_VERB(edit_admin_permissions, R_PERMISSIONS, "Permissions Panel", "Edit adm
590,
allowed_edit_field = usr.client.holder.can_edit_rights_flags(),
)
if(isnull(new_flags))
return
admin_holder.disassociate()
+6 -1
View File
@@ -151,7 +151,10 @@
log_and_message_admins("[ckey] has registered their Discord ID. Their Discord snowflake ID is: [their_id]", src) //YW EDIT
admin_chat_message(message = "[ckey] has registered their Discord ID. Their Discord is: <@[their_id]>", color = "#4eff22") //YW EDIT
notes_add(ckey, "Discord ID: [their_id]")
world.VgsAddMemberRole(their_id)
var/port = CONFIG_GET(number/register_server_port)
if(port)
// Designed to be used with `tools/registration`
world.Export("http://127.0.0.1:[port]?member=[url_encode(json_encode(their_id))]")
else
to_chat(src, span_warning("There was an error registering your Discord ID in the database. Contact an administrator."))
log_and_message_admins("[ckey] failed to register their Discord ID. Their Discord snowflake ID is: [their_id]. Is the database connected?", src)
@@ -352,6 +355,8 @@
alert = TRUE
if(alert)
for(var/client/X in GLOB.admins)
if(!check_rights_for(X, R_HOLDER))
continue
if(X.prefs?.read_preference(/datum/preference/toggle/holder/play_adminhelp_ping))
X << 'sound/voice/bcriminal.ogg' //ChompEDIT - back to beepsky
window_flash(X)
+3 -1
View File
@@ -402,8 +402,10 @@ var/list/preferences_datums = list()
if(tgui_alert(user, "Are you sure you want to override slot [slotnum], [choice]'s savedata?", "Confirm Override", list("No", "Yes")) == "Yes")
overwrite_character(slotnum)
sanitize_preferences()
save_character()
save_preferences()
save_character()
load_preferences(TRUE)
load_character()
attempt_vr(user.client?.prefs_vr,"load_vore","")
ShowChoices(user)
+10 -10
View File
@@ -136,8 +136,8 @@
switch(action)
// Basic actions
if("load")
if(!IsGuestKey(usr.key))
open_load_dialog(usr)
if(!IsGuestKey(ui.user.key))
open_load_dialog(ui.user)
. = TRUE
if("save")
save_character()
@@ -146,22 +146,22 @@
VARSET_IN(src, saved_notification, FALSE, 1 SECONDS)
. = TRUE
if("reload")
load_preferences()
load_preferences(TRUE)
load_character()
attempt_vr(client.prefs_vr,"load_vore","") //VOREStation Edit
sanitize_preferences()
. = TRUE
if("resetslot")
if("Yes" != tgui_alert(usr, "This will reset the current slot. Continue?", "Reset current slot?", list("No", "Yes")))
if("Yes" != tgui_alert(ui.user, "This will reset the current slot. Continue?", "Reset current slot?", list("No", "Yes")))
return
if("Yes" != tgui_alert(usr, "Are you completely sure that you want to reset this character slot?", "Reset current slot?", list("No", "Yes")))
if("Yes" != tgui_alert(ui.user, "Are you completely sure that you want to reset this character slot?", "Reset current slot?", list("No", "Yes")))
return
reset_slot()
sanitize_preferences()
. = TRUE
if("copy")
if(!IsGuestKey(usr.key))
open_copy_dialog(usr)
if(!IsGuestKey(ui.user.key))
open_copy_dialog(ui.user)
. = TRUE
// More specific stuff
if("switch_category")
@@ -169,11 +169,11 @@
for(var/datum/category_group/player_setup_category/PS in player_setup.categories)
if(PS.name == new_category)
player_setup.selected_category = PS
update_tgui_static_data(usr, ui)
update_tgui_static_data(ui.user, ui)
break
. = TRUE
if("game_prefs")
usr.client.game_options()
ui.user.client.game_options()
. = TRUE
if("refresh_character_preview")
if(!COOLDOWN_FINISHED(src, ui_refresh_cooldown))
@@ -192,7 +192,7 @@
PMH.screen_loc = LAZYACCESS(preview_screen_locs, "PMH")
/datum/preferences/tgui_close(mob/user)
save_character()
// save_character()
save_preferences()
/datum/preferences/proc/create_character_profiles()
+1 -1
View File
@@ -163,7 +163,7 @@
// Admins with RLOOC displayed who weren't already in
for(var/client/admin in GLOB.admins)
if(!(admin in receivers) && admin.prefs?.read_preference(/datum/preference/toggle/holder/show_rlooc))
if(check_rights_for(admin, R_ADMIN|R_SERVER)) //Stop rLOOC showing for retired staff //CHOMPEdit, admins should see LOOC
if(check_rights_for(admin, (R_SERVER|R_ADMIN))) //Stop rLOOC showing for retired staff
r_receivers |= admin
msg = GLOB.is_valid_url.Replace(msg,span_linkify("$1"))
+8 -2
View File
@@ -1,3 +1,5 @@
#define NO_ADMINS_ONLINE_MESSAGE "Adminhelps are also sent through TGS to services like Discord. If no admins are available in game, sending an adminhelp might still be noticed and responded to."
/client/verb/who()
set name = "Who"
set category = "OOC.Resources"
@@ -58,6 +60,8 @@
set category = "Admin"
set name = "Staffwho"
var/header = GLOB.admins.len == 0 ? "No Admins Currently Online" : "Current Admins"
var/msg = ""
var/modmsg = ""
var/devmsg = ""
@@ -132,6 +136,8 @@
if(CONFIG_GET(flag/show_mentors))
msg += "\n" + span_bold(" Current Mentors ([num_mentors_online]):") + "\n" + mentormsg
msg += "\n" + span_info("Adminhelps are also sent to Discord. If no admins are available in game try anyway and an admin on Discord may see it and respond.")
msg += "\n" + span_info(NO_ADMINS_ONLINE_MESSAGE)
to_chat(src,span_filter_notice("[jointext(msg, "<br>")]"))
to_chat(src, fieldset_block(span_bold(header), span_filter_notice("[jointext(msg, "<br>")]"), "boxed_message"), type = MESSAGE_TYPE_INFO)
#undef NO_ADMINS_ONLINE_MESSAGE
+1 -1
View File
@@ -656,7 +656,7 @@ var/global/list/light_type_cache = list()
playsound(src, W.usesound, 75, 1)
user.visible_message("[user.name] opens [src]'s casing.", \
"You open [src]'s casing.", "You hear a noise.")
new construct_type(src.loc, fixture = src)
new construct_type(src.loc, src)
qdel(src)
return
-3
View File
@@ -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"
-3
View File
@@ -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"
-90
View File
@@ -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)
-6
View File
@@ -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))
-3
View File
@@ -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
@@ -116,3 +116,15 @@
/datum/tgs_chat_command/vore/Run(datum/tgs_chat_user/sender, params)
return "vore"
// - FAX
/datum/tgs_chat_command/readfax
name = "readfax"
help_text = "Reads a fax with specified faxid"
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")
return "FAX: ```[strip_html_properly(faxmsg)]```"
@@ -8,23 +8,21 @@
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
var/map_name = "n/a"
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++
for(var/client/C in GLOB.clients)
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
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()]\n**Current Map:** [map_name]" // CHOMPEdit
/datum/tgs_chat_command/parsetest
name = "parsetest"
@@ -140,21 +138,3 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations)
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 -1
View File
@@ -55,7 +55,7 @@ ADMIN_VERB(cmd_mentor_ticket_panel, (R_ADMIN|R_SERVER|R_MOD|R_MENTOR), "Mentor T
GLOB.tickets.BrowseTickets(browse_to)
/proc/message_mentors(var/msg)
msg = span_mentor_channel(span_prefix("Mentor:") + span_message("[msg]"))
msg = span_mentor_channel(span_prefix("Mentor: ") + span_message("[msg]"))
for(var/client/C in GLOB.admins)
to_chat(C, msg)
+22 -16
View File
@@ -20,6 +20,7 @@
else
world.TgsTargetedChatBroadcast(message,TRUE)
//
//TICKET MANAGER
//
@@ -318,9 +319,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
var/list/activemins = adm["present"]
var activeMins = activemins.len
if(is_bwoink)
ahelp_discord_message("ADMINHELP: FROM: [key_name_admin(usr)] TO [initiator_ckey]/[initiator_key_name] - MSG: **[msg]** - Heard by [activeMins] NON-AFK staff members.")
ahelp_discord_message("[level == 0 ? "MENTORHELP" : "ADMINHELP"]: FROM: [key_name_admin(usr)] TO [initiator_ckey]/[initiator_key_name] - MSG: **[msg]** - Heard by [activeMins] NON-AFK staff members.")
else
ahelp_discord_message("ADMINHELP: FROM: [initiator_ckey]/[initiator_key_name] - MSG: **[msg]** - Heard by [activeMins] NON-AFK staff members.")
ahelp_discord_message("[level == 0 ? "MENTORHELP" : "ADMINHELP"]: FROM: [initiator_ckey]/[initiator_key_name] - MSG: **[msg]** - Heard by [activeMins] NON-AFK staff members.")
// Also send it to discord since that's the hip cool thing now.
SSwebhooks.send(
@@ -357,11 +358,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
tgui_interact(usr.client.mob)
//private
/datum/ticket/proc/FullMonty(ref_src, admin = FALSE)
/datum/ticket/proc/FullMonty(ref_src, admin_commands = FALSE)
if(!ref_src)
ref_src = "\ref[src]"
if(initiator && initiator.mob)
if(admin)
if(admin_commands)
. = ADMIN_FULLMONTY_NONAME(initiator.mob)
else
. = "Initiator disconnected."
@@ -403,22 +404,26 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
//won't bug irc
/datum/ticket/proc/MessageNoRecipient(msg)
var/ref_src = "\ref[src]"
var/chat_msg = span_admin_pm_notice(span_adminhelp("Ticket [TicketHref("#[id]", ref_src)]") + span_bold(": [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:") + msg)
AddInteraction(span_red("[LinkedReplyName(ref_src)]: [msg]"))
//send this msg to all admins
if(level == 0)
for (var/client/C in GLOB.admins)
if (C.prefs?.read_preference(/datum/preference/toggle/play_mentorhelp_ping))
C << 'sound/effects/mentorhelp.mp3'
message_mentors(chat_msg)
else if(level == 1)
for(var/client/X in GLOB.admins)
if(X.prefs?.read_preference(/datum/preference/toggle/holder/play_adminhelp_ping))
X << 'sound/effects/adminhelp.ogg'
window_flash(X)
to_chat(X, chat_msg)
switch(level)
if(0)
for (var/client/C in GLOB.admins)
var/chat_msg = span_mentor_channel(span_admin_pm_notice(span_adminhelp("Ticket [TicketHref("#[id]", ref_src)]") + span_bold(" (Mentor): [LinkedReplyName(ref_src)] [FullMonty(ref_src, check_rights_for(C, (R_ADMIN|R_SERVER|R_MOD)))]:") + msg))
if (C.prefs?.read_preference(/datum/preference/toggle/play_mentorhelp_ping))
C << 'sound/effects/mentorhelp.mp3'
to_chat(C, chat_msg)
if(1)
for(var/client/X in GLOB.admins)
var/chat_msg = span_admin_pm_notice(span_adminhelp("Ticket [TicketHref("#[id]", ref_src)] (Admin)") + span_bold(": [LinkedReplyName(ref_src)] [FullMonty(ref_src, check_rights_for(X, (R_ADMIN|R_SERVER|R_MOD)))]:") + msg)
if(!check_rights_for(X, R_HOLDER))
continue
if(X.prefs?.read_preference(/datum/preference/toggle/holder/play_adminhelp_ping))
X << 'sound/effects/adminhelp.ogg'
window_flash(X)
to_chat(X, chat_msg)
/*
//Reopen a closed ticket
@@ -649,6 +654,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick/ticket_list)
level = level + 1
AddInteraction("[key_name_admin(usr)] escalated Ticket.")
message_mentors("[usr.ckey] escalated Ticket [TicketHref("#[id]")]")
log_admin("[key_name(usr)] escalated ticket [src.name]")
to_chat(src.initiator, span_mentor("[usr.ckey] escalated your ticket to admins."))
+3 -3
View File
@@ -45,7 +45,7 @@
"closed_at" = (world.time - T.closed_at),
"opened_at_date" = gameTimestamp(wtime = T.opened_at),
"closed_at_date" = gameTimestamp(wtime = T.closed_at),
"actions" = check_rights_for(user.client, (R_ADMIN|R_SERVER|R_MOD)) ? T.FullMonty(,TRUE) : T.FullMonty(),
"actions" = T.FullMonty(null, check_rights_for(user.client, (R_ADMIN|R_SERVER|R_MOD))),
"log" = T._interactions,
)
@@ -235,7 +235,7 @@
data["opened_at_date"] = gameTimestamp(wtime = opened_at)
data["closed_at_date"] = gameTimestamp(wtime = closed_at)
data["actions"] = check_rights_for(user.client, (R_ADMIN|R_SERVER|R_MOD)) ? FullMonty(ref_src, TRUE) : FullMonty(ref_src)
data["actions"] = FullMonty(ref_src, check_rights_for(user.client, (R_ADMIN|R_SERVER|R_MOD)))
data["log"] = _interactions
@@ -296,7 +296,7 @@
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [(world.time - closed_at) / 600] minutes ago)"
dat += "<br><br>"
if(initiator)
dat += span_bold("Actions:") + " [check_rights_for(user.client, (R_ADMIN|R_SERVER|R_MOD)) ? FullMonty(ref_src, TRUE) : FullMonty(ref_src)]<br>"
dat += span_bold("Actions:") + " [FullMonty(ref_src, check_rights_for(user.client, (R_ADMIN|R_SERVER|R_MOD)))]<br>"
else
dat += span_bold("DISCONNECTED") + "[GLOB.TAB][ClosureLinks(ref_src)]<br>"
dat += "<br><b>Log:</b><br><br>"
+5 -4
View File
@@ -473,10 +473,8 @@ ITEMS_SURVIVE_DIGESTION
# Path to the folder that BYOND should export faxes into so they are readable on the web.
#FAX_EXPORT_DIR data/faxes
# TCP port on which to connect to the VGS instance.
#VGS_SERVER_PORT 8888
# Secret pre-shared-key to authenticate to VGS.
#VGS_ACCESS_IDENTIFIER some_password_here
# Port for helper script to add member roles in discord (see tools/registration)
#REGISTER_SERVER_PORT 6969
MULTI_Z_EXPLOSION_SCALAR 0.35
@@ -623,3 +621,6 @@ JUKEBOX_TRACK_FILES config/jukebox.json
#Turn this on if you want all admin-PMs to go to be sent to discord, and not only the first message of a ticket.
#DISCORD_AHELPS_ALL
## Uncomment to set the number of /world/Reboot()s before the DreamDaemon restarts itself. 0 means restart every round. Requires tgstation server tools.
#ROUNDS_UNTIL_HARD_RESTART 10
+1 -1
View File
@@ -8,7 +8,7 @@ export BYOND_MAJOR=516
export BYOND_MINOR=1664
# Macro Count
export MACRO_COUNT=8
export MACRO_COUNT=9
#rust_g git tag
export RUST_G_VERSION=3.11.0
+54 -10
View File
@@ -1,10 +1,54 @@
body {padding:0px;margin:0px;}
#top {position:fixed;top:5px;left:10%;width:80%;text-align:center;background-color:#fff;border:2px solid #ccc;}
#main {position:relative;top:10px;left:3%;width:96%;text-align:center;z-index:0;}
#searchable {table-layout:fixed;width:100%;text-align:center;"#f4f4f4";}
tr.norm {background-color:#f4f4f4;}
tr.title {background-color:#ccc;}
tr.alt {background-color:#e7e7e7;}
.small {font-size:80%;}
a {text-decoration:none;}
a:hover {color:#d3d;}
body {
padding: 0px;
margin: 0px;
}
#top {
position: fixed;
top: 5px;
left: 10%;
width: 80%;
text-align: center;
background-color: #fff;
border: 2px solid #ccc;
}
#main {
position: relative;
top: 10px;
left: 3%;
width: 96%;
text-align: center;
z-index: 0;
}
#searchable {
table-layout: fixed;
width: 100%;
text-align: center;
background-color: "#f4f4f4";
}
tr.norm {
background-color: #f4f4f4;
}
tr.title {
background-color: #ccc;
}
tr.alt {
background-color: #e7e7e7;
}
.small {
font-size: 80%;
}
a {
text-decoration: none;
}
a:hover {
color: #d3d;
}
+369 -273
View File
@@ -1,422 +1,518 @@
body
{
padding: 0;
margin: 0;
background-color: #272727;
font-size: 12px;
color: #ffffff;
line-height: 170%;
body {
padding: 0;
margin: 0;
background-color: #272727;
font-size: 12px;
color: #ffffff;
line-height: 170%;
}
hr
{
background-color: #40628a;
height: 1px;
hr {
background-color: #40628a;
height: 1px;
}
a, a:link, a:visited, a:active, .linkOn, .linkOff
{
color: #ffffff;
text-decoration: none;
background: #40628a;
border: 1px solid #161616;
padding: 1px 4px 1px 4px;
margin: 0 2px 0 0;
cursor:default;
white-space:nowrap;
a,
button,
a:link,
a:visited,
a:active,
.linkOn,
.linkOff {
color: #ffffff;
text-decoration: none;
background: #40628a;
border: 1px solid #161616;
padding: 1px 4px 1px 4px;
margin: 0 2px 0 0;
cursor: default;
}
a:hover
{
color: #40628a;
background: #ffffff;
a:hover {
color: #40628a;
background: #ffffff;
}
a.white, a.white:link, a.white:visited, a.white:active
{
color: #40628a;
text-decoration: none;
background: #ffffff;
border: 1px solid #161616;
padding: 1px 4px 1px 4px;
margin: 0 2px 0 0;
cursor:default;
a.white,
a.white:link,
a.white:visited,
a.white:active {
color: #40628a;
text-decoration: none;
background: #ffffff;
border: 1px solid #161616;
padding: 1px 4px 1px 4px;
margin: 0 2px 0 0;
cursor: default;
}
a.white:hover
{
color: #ffffff;
background: #40628a;
a.white:hover {
color: #ffffff;
background: #40628a;
}
.linkOn, a.linkOn:link, a.linkOn:visited, a.linkOn:active, a.linkOn:hover
{
color: #ffffff;
background: #2f943c;
border-color: #24722e;
.linkOn,
a.linkOn:link,
a.linkOn:visited,
a.linkOn:active,
a.linkOn:hover {
color: #ffffff;
background: #2f943c;
border-color: #24722e;
}
.linkOff, a.linkOff:link, a.linkOff:visited, a.linkOff:active, a.linkOff:hover
{
color: #ffffff;
background: #999999;
border-color: #666666;
.linkOff,
a.linkOff:link,
a.linkOff:visited,
a.linkOff:active,
a.linkOff:hover {
color: #ffffff;
background: #999999;
border-color: #666666;
}
a.icon, .linkOn.icon, .linkOff.icon
{
position: relative;
padding: 1px 4px 2px 20px;
a.icon,
.linkOn.icon,
.linkOff.icon {
position: relative;
padding: 1px 4px 2px 20px;
}
a.icon img, .linkOn.icon img
{
position: absolute;
top: 0;
left: 0;
width: 18px;
height: 18px;
a.icon img,
.linkOn.icon img {
position: absolute;
top: 0;
left: 0;
width: 18px;
height: 18px;
}
a.icon64, .linkOn.icon64, .linkOff.icon64
{
position: relative;
padding: 1px 4px 2px 68px;
font-size: 55px;
a.icon64,
.linkOn.icon64,
.linkOff.icon64 {
position: relative;
padding: 1px 4px 2px 68px;
font-size: 55px;
}
a.icon64 img, .linkOn.icon64 img
{
position: absolute;
top: 0;
left: 0;
width: 66px;
height: 66px;
a.icon64 img,
.linkOn.icon64 img {
position: absolute;
top: 0;
left: 0;
width: 66px;
height: 66px;
}
ul
{
padding: 4px 0 0 10px;
margin: 0;
list-style-type: none;
ul {
padding: 4px 0 0 10px;
margin: 0;
list-style-type: none;
}
li
{
padding: 0 0 2px 0;
li {
padding: 0 0 2px 0;
}
img, a img
{
border-style:none;
img,
a img {
border-style: none;
}
h1, h2, h3, h4, h5, h6
{
margin: 0;
padding: 16px 0 8px 0;
color: #517087;
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 16px 0 8px 0;
color: #517087;
}
h1
{
font-size: 15px;
h1 {
font-size: 15px;
}
h2
{
font-size: 14px;
h2 {
font-size: 14px;
}
h3
{
font-size: 13px;
h3 {
font-size: 13px;
}
h4
{
font-size: 12px;
h4 {
font-size: 12px;
}
.uiWrapper
{
width: 100%;
height: 100%;
padding-top:32px;
.uiWrapper {
width: 100%;
height: 100%;
}
.uiTitle
{
clear: both;
padding: 6px 8px 6px 8px;
border-bottom: 2px solid #161616;
background: #383838;
color: #98B0C3;
font-size: 16px;
.uiTitle {
clear: both;
padding: 6px 8px 6px 8px;
border-bottom: 2px solid #161616;
background: #383838;
color: #98b0c3;
font-size: 16px;
}
.uiTitleWrapper
{
position:fixed;
top:0px;
left:0px;
right:0px;
z-index: 10
.uiTitle.icon {
padding: 6px 8px 6px 42px;
background-position: 2px 50%;
background-repeat: no-repeat;
}
.uiTitleButtons
{
position:fixed;
top:0px;
right:0px;
height:32px;
z-index:11;
.uiContent {
clear: both;
padding: 8px;
font-family: Verdana, Geneva, sans-serif;
}
.uiTitle.icon
{
padding: 6px 8px 6px 42px;
background-position: 2px 50%;
background-repeat: no-repeat;
.good,
.green {
color: #00ff00;
}
.uiContent
{
clear: both;
padding: 8px;
font-family: Verdana, Geneva, sans-serif;
.average,
.orange {
color: #d09000;
}
.good, .green
{
color: #00ff00;
.bad,
.red {
color: #ff0000;
}
.average, .orange
{
color: #d09000;
.highlight {
color: #8BA5C4;
}
.bad, .red
{
color: #ff0000;
}
.highlight
{
color: #8BA5C4;
}
.dark
{
color: #272727;
.dark {
color: #272727;
}
.darkgreen {
color: #008000;
color: #008000;
}
.grey {
color: #838383;
color: #838383;
}
.crimson {
color: #dc143c;
color: #dc143c;
}
.maroon {
color: #800000;
color: #800000;
}
.brown {
color: #8d4925;
color: #8d4925;
}
.blue {
color: #0000ff;
color: #0000ff;
}
.black {
color: #000000;
color: #000000;
}
.white {
color: #000000;
color: #000000;
}
.darkgray {
color: #808080;
color: #808080;
}
.gray {
color: #a9a9a9;
color: #a9a9a9;
}
.yellow {
color: #ffcc00;
color: #ffcc00;
}
.pink {
color: #ffc0cb;
color: #ffc0cb;
}
.cyan {
color: #00ffff;
color: #00ffff;
}
.nicegreen {
color: #14a833;
color: #14a833;
}
.notice
{
position: relative;
background: #E9C183;
color: #15345A;
font-size: 10px;
font-style: italic;
padding: 2px 4px 0 4px;
margin: 4px;
.notice {
position: relative;
background: #e9c183;
color: #15345a;
font-size: 10px;
font-style: italic;
padding: 2px 4px 0 4px;
margin: 4px;
}
.boldnotice
{
position: relative;
background: #E9C183;
color: #15345A;
font-weight: bold;
font-size: 10px;
font-style: italic;
padding: 2px 4px 0 4px;
margin: 4px;
.boldnotice {
position: relative;
background: #E9C183;
color: #15345A;
font-weight: bold;
font-size: 10px;
font-style: italic;
padding: 2px 4px 0 4px;
margin: 4px;
}
.notice.icon
{
padding: 2px 4px 0 20px;
.notice.icon {
padding: 2px 4px 0 20px;
}
.notice img
{
position: absolute;
top: 0;
left: 0;
width: 16px;
height: 16px;
.notice img {
position: absolute;
top: 0;
left: 0;
width: 16px;
height: 16px;
}
div.notice
{
clear: both;
div.notice {
clear: both;
}
.statusDisplay
{
background: #000000;
color: #ffffff;
border: 1px solid #40628a;
padding: 4px;
margin: 3px 0;
.statusDisplay {
background: #000000;
color: #ffffff;
border: 1px solid #40628a;
padding: 4px;
margin: 3px 0;
}
.block
{
padding: 8px;
margin: 10px 4px 4px 4px;
border: 1px solid #40628a;
background-color: #202020;
.statusLabel {
width: 138px;
float: left;
overflow: hidden;
color: #98b0c3;
}
.block h3
{
padding: 0;
.statusValue {
float: left;
}
.progressBar
{
width: 240px;
height: 14px;
border: 1px solid #666666;
float: left;
margin: 0 5px;
overflow: hidden;
.block {
padding: 8px;
margin: 10px 4px 4px 4px;
border: 1px solid #40628a;
background-color: #202020;
}
.progressFill
{
width: 100%;
height: 100%;
background: #40628a;
overflow: hidden;
.block h3 {
padding: 0;
}
.progressFill.good
{
color: #ffffff;
background: #00ff00;
.progressBar {
width: 240px;
height: 14px;
border: 1px solid #666666;
float: left;
margin: 0 5px;
overflow: hidden;
}
.progressFill.average
{
color: #ffffff;
background: #d09000;
.progressFill {
width: 100%;
height: 100%;
background: #40628a;
overflow: hidden;
}
.progressFill.bad
{
color: #ffffff;
background: #ff0000;
.progressFill.good {
color: #ffffff;
background: #00ff00;
}
.progressFill.highlight
{
color: #ffffff;
background: #8BA5C4;
.progressFill.average {
color: #ffffff;
background: #d09000;
}
.clearBoth
{
clear: both;
.progressFill.bad {
color: #ffffff;
background: #ff0000;
}
.clearLeft
{
clear: left;
.progressFill.highlight {
color: #ffffff;
background: #8ba5c4;
}
.clearRight
{
clear: right;
.clearBoth {
clear: both;
}
.line
{
width: 100%;
clear: both;
.clearLeft {
clear: left;
}
.clearRight {
clear: right;
}
.line {
width: 100%;
clear: both;
}
.italic,
.italics {
font-style: italic;
font-style: italic;
}
.bold {
font-weight: bold;
font-weight: bold;
}
.underline {
text-decoration: underline;
text-decoration: underline;
}
.spoiler{
background-color: gray;
color: transparent;
user-select: none;
.spoiler {
background-color: gray;
color: transparent;
user-select: none;
}
.spoiler:hover{
background-color: inherit;
color: inherit;
.spoiler:hover {
background-color: inherit;
color: inherit;
}
.switch {
position: relative;
display: inline-block;
width: 50px;
height: 26px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #383838;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 4px;
bottom: 4px;
background-color: #98b0c3;
transition: 0.4s;
}
.slider.red:before {
background-color: #d6858b;
}
.slider.locked:before {
content: url("padlock.png");
background-color: #b4b4b4;
}
input:checked+.slider {
background-color: #40628a;
}
input:checked+.slider.red {
background-color: #a92621;
}
input:checked+.slider.locked {
background-color: #707070;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196f3;
}
input:focus+.slider.red {
box-shadow: 0 0 1px #f3212d;
}
input:focus+.slider.locked {
box-shadow: 0 0 1px #979797;
}
input:checked+.slider:before {
transform: translateX(24px);
}
.switch span {
display: inline-block;
position: relative;
width: 60px;
margin-left: 60px;
}
ul.sparse {
padding-bottom: 20px;
}
.sparse li {
margin-top: 2px;
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.severity {
margin: 0px;
padding: 1px 8px 1px 8px;
border-radius: 25px;
border: 1px solid #161616;
background: #40628a;
color: #ffffff;
}
.severity img {
display: inline-block;
vertical-align: middle;
}
.code {
padding: 6px 8px;
border: 1px solid #161616;
background: #383838;
color: #ffffff;
font-size: 12px;
display: block;
margin: 4px 0;
font-family: "Courier New", Courier, monospace;
}
.user-select {
user-select: all;
}
+9 -9
View File
@@ -68,20 +68,20 @@ will need these:
**Via Juke Build (cross-platform)**:
- `tools/build/build tgui` - Build tgui in production mode.
- `tools/build/build tgui-dev` - Build tgui in production mode.
- `tools/build/build tgui-dev --reload` - Reload byond cache once.
- `tools/build/build tgui-dev --debug` - Run server with debug logging
- `tools/build/build.sh tgui` - Build tgui in production mode.
- `tools/build/build.sh tgui-dev` - Build tgui in production mode.
- `tools/build/build.sh tgui-dev --reload` - Reload byond cache once.
- `tools/build/build.sh tgui-dev --debug` - Run server with debug logging
enabled.
- `tools/build/build tgui-lint` - Show (and auto-fix) problems with the code.
- `tools/build/build tgui-test` - Run unit and integration tests.
- `tools/build/build tgui-analyze` - Run a bundle analyzer.
- `tools/build/build tgui-clean` - Clean up tgui folder.
- `tools/build/build.sh tgui-lint` - Show (and auto-fix) problems with the code.
- `tools/build/build.sh tgui-test` - Run unit and integration tests.
- `tools/build/build.sh tgui-analyze` - Run a bundle analyzer.
- `tools/build/build.sh tgui-clean` - Clean up tgui folder.
> With Juke Build, you can run multiple targets together, e.g.:
>
> ```
> tools/build/build tgui tgui-lint tgui-tsc tgui-test
> tools/build/build.sh tgui tgui-lint tgui-tsc tgui-test
> ```
**Via Bun (cross-platform)**:
@@ -1126,6 +1126,70 @@ img.icon.bigicon {
border-bottom: 1px dashed hsl(0, 0%, 100%);
}
.fieldset_legend {
position: relative;
max-width: 95%;
font-size: 120%;
background-color: var(--color-section);
padding: var(--space-s) var(--space-m);
border-color: inherit;
z-index: 0;
&:before {
content: '';
position: absolute;
inset: 0;
border: var(--border-thickness-tiny) solid;
border-color: inherit;
border-radius: var(--border-radius-medium);
mask-image: linear-gradient(to top, black 50%, transparent 50%);
z-index: -1;
}
}
.boxed_message {
background: hsl(220, 10%, 10%);
border: var(--border-thickness-tiny) solid;
border-left: var(--border-thickness-large) solid;
border-color: hsla(220, 40%, 75%, 0.25);
margin: var(--space-m) 0;
padding: var(--space-m) var(--space-l);
border-radius: var(--border-radius-medium);
&.red_box {
background: hsl(0, 20%, 10%);
border-color: hsla(0, 100%, 50%, 0.5);
}
&.green_box {
background: hsl(140, 20%, 10%);
border-color: hsla(120, 100%, 50%, 0.5);
}
&.blue_box {
background: hsl(220, 20%, 10%);
border-color: hsla(225, 90%, 65%, 0.5);
}
&.purple_box {
background: hsl(260, 25%, 12.5%);
border-color: hsla(260, 100%, 75%, 0.5);
}
hr {
margin: var(--space-m) -0.75em;
border-color: inherit;
}
}
// Provides a horizontal bar with text in the middle
// I got this off stackoverflow
.separator {
display: flex;
align-items: center;
text-align: center;
}
$alert-stripe-colors: (
'default': hsl(199, 100%, 11%),
'green': hsl(120, 100%, 12%),
@@ -1148,6 +1148,47 @@ h2.alert {
border-bottom: 1px dashed hsl(0, 0%, 0%);
}
.fieldset_legend {
background: hsl(0, 0%, 100%); // Chat background color
&:before {
background: hsl(0, 0%, 100%); // Chat background color
}
}
.boxed_message {
background: hsl(220, 100%, 97.5%);
border-color: hsla(220, 75%, 25%, 0.5);
&.red_box {
background: hsl(0, 100%, 97.5%);
border-color: hsla(0, 100%, 50%, 0.5);
}
&.green_box {
background: hsl(140, 100%, 97.5%);
border-color: hsl(120, 100%, 33%, 0.5);
}
&.blue_box {
background: hsl(220, 100%, 97.5%);
border-color: hsla(225, 100%, 50%, 0.5);
}
&.purple_box {
background: hsl(260, 100%, 97.5%);
border-color: hsla(260, 100%, 50%, 0.5);
}
}
// Provides a horizontal bar with text in the middle
// I got this off stackoverflow
.separator {
display: flex;
align-items: center;
text-align: center;
}
$alert-stripe-colors: (
'default': hsl(231, 100%, 85%),
'green': hsl(120, 100%, 84%),
@@ -1127,6 +1127,70 @@ img.icon.bigicon {
border-bottom: 1px dashed hsl(0, 0%, 100%);
}
.fieldset_legend {
position: relative;
max-width: 95%;
font-size: 120%;
background-color: var(--color-section);
padding: var(--space-s) var(--space-m);
border-color: inherit;
z-index: 0;
&:before {
content: '';
position: absolute;
inset: 0;
border: var(--border-thickness-tiny) solid;
border-color: inherit;
border-radius: var(--border-radius-medium);
mask-image: linear-gradient(to top, black 50%, transparent 50%);
z-index: -1;
}
}
.boxed_message {
background: hsl(220, 10%, 10%);
border: var(--border-thickness-tiny) solid;
border-left: var(--border-thickness-large) solid;
border-color: hsla(220, 40%, 75%, 0.25);
margin: var(--space-m) 0;
padding: var(--space-m) var(--space-l);
border-radius: var(--border-radius-medium);
&.red_box {
background: hsl(0, 20%, 10%);
border-color: hsla(0, 100%, 50%, 0.5);
}
&.green_box {
background: hsl(140, 20%, 10%);
border-color: hsla(120, 100%, 50%, 0.5);
}
&.blue_box {
background: hsl(220, 20%, 10%);
border-color: hsla(225, 90%, 65%, 0.5);
}
&.purple_box {
background: hsl(260, 25%, 12.5%);
border-color: hsla(260, 100%, 75%, 0.5);
}
hr {
margin: var(--space-m) -0.75em;
border-color: inherit;
}
}
// Provides a horizontal bar with text in the middle
// I got this off stackoverflow
.separator {
display: flex;
align-items: center;
text-align: center;
}
$alert-stripe-colors: (
'default': hsl(199, 100%, 11%),
'green': hsl(120, 100%, 12%),
@@ -1146,6 +1146,47 @@ h2.alert {
border-bottom: 1px dashed hsl(0, 0%, 0%);
}
.fieldset_legend {
background: hsl(0, 0%, 100%); // Chat background color
&:before {
background: hsl(0, 0%, 100%); // Chat background color
}
}
.boxed_message {
background: hsl(220, 100%, 97.5%);
border-color: hsla(220, 75%, 25%, 0.5);
&.red_box {
background: hsl(0, 100%, 97.5%);
border-color: hsla(0, 100%, 50%, 0.5);
}
&.green_box {
background: hsl(140, 100%, 97.5%);
border-color: hsl(120, 100%, 33%, 0.5);
}
&.blue_box {
background: hsl(220, 100%, 97.5%);
border-color: hsla(225, 100%, 50%, 0.5);
}
&.purple_box {
background: hsl(260, 100%, 97.5%);
border-color: hsla(260, 100%, 50%, 0.5);
}
}
// Provides a horizontal bar with text in the middle
// I got this off stackoverflow
.separator {
display: flex;
align-items: center;
text-align: center;
}
$alert-stripe-colors: (
'default': hsl(231, 100%, 85%),
'green': hsl(120, 100%, 84%),
+5
View File
@@ -37,6 +37,11 @@ function Get-Bun {
$BunTag = " (baseline)"
}
if (Test-Path $BunTargetDir -PathType Container) {
Write-Output "Bun target directory exists but bun.exe is missing. Re-downloading."
Remove-Item $BunTargetDir -Recurse -Force
}
$BunSource = "https://github.com/oven-sh/bun/releases/download/bun-v$BunVersion/$BunRelease.zip"
Write-Output "Downloading Bun v$BunVersion$BunTag"
+2 -2
View File
@@ -9,7 +9,7 @@ This build script is the recommended way to compile the game, including not only
a) Double-click `BUILD.bat` in the repository root to build (will wait for a key press before it closes).
b) Double-click `tools/build/build.bat` to build (will exit as soon as it finishes building).
- Linux:
a) Run `tools/build/build` from the repository root.
a) Run `tools/build/build.sh` from the repository root.
The script will skip build steps whose inputs have not changed since the last run.
@@ -18,7 +18,7 @@ The script will skip build steps whose inputs have not changed since the last ru
You can get a list of all targets that you can build by running the following command:
```
tools/build/build --help
tools/build/build.sh --help
```
## Dependencies
+2
View File
@@ -0,0 +1,2 @@
node_modules/
config.json
+6
View File
@@ -0,0 +1,6 @@
{
"port": 6969,
"token": "your-token-goes-here",
"guildId": "your-guild-snowflake-goes-here",
"roleId": "your-role-snowflake-goes-here"
}
+72
View File
@@ -0,0 +1,72 @@
const http = require("node:http");
const { Client, GatewayIntentBits } = require("discord.js");
const { port, token, guildId, roleId } = require("./config.json");
async function main() {
const client = new Client({ intents: [] });
await client.login(token);
const guild = await client.guilds.fetch(guildId);
if (!guild) {
console.error("ERROR in config, unable to resolve guild " + guildId);
return;
}
const role = await guild.roles.fetch(roleId);
if (!role) {
console.error("ERROR in config, invalid role ID ", roleId);
return;
}
const server = http.createServer({}, (req, res) => {
const url = req.url;
if (!url) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ data: "error parsing URL" }))
return;
}
let urlObj;
try {
urlObj = new URL(`http://localhost${url}`);
} catch (err) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ data: "error parsing URL: " + err }))
return;
}
if (!urlObj.search) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ data: "error parsing URL" }))
return;
}
const params = urlObj.searchParams;
const member_id = params.get("member");
if (!member_id) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ data: "error parsing URL" }))
return;
}
let memberIdRaw;
try {
memberIdRaw = JSON.parse(member_id);
} catch(err) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ data: "error parsing URL: " + err }))
return;
}
guild.members.addRole({ user: memberIdRaw, role, reason: "SS13 Registration" })
console.log("Successfully registered ", memberIdRaw);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ data: "success" }))
});
server.listen(port);
console.log("Server running on port", port);
}
main();
+14
View File
@@ -0,0 +1,14 @@
{
"name": "registration",
"version": "1.0.0",
"description": "Small discord.js bot to handle adding member roles on discord registration",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "tigercat2000",
"license": "MIT",
"dependencies": {
"discord.js": "^14.21.0"
}
}
+24 -5
View File
@@ -6,22 +6,31 @@ has_git="$(command -v git)"
has_curl="$(command -v curl)"
has_cargo="$(command -v ~/.cargo/bin/cargo)"
has_sudo="$(command -v sudo)"
# FIXME: yt-dlp
has_ytdlp="$(command -v yt-dlp)"
has_pip3="$(command -v pip3)"
has_unzip="$(command -v unzip)"
set -e
set -x
# apt packages, libssl needed by rust-g but not included in TGS barebones install
if ! ( [ -x "$has_git" ] && [ -x "$has_curl" ] && [ -f "/usr/lib/i386-linux-gnu/libssl.so" ] ); then
echo "Installing apt dependencies..."
if ! ( [ -x "$has_git" ] && [ -x "$has_curl" ] && [ -x "$has_pip3" ] && [ -x "$has_unzip" ] && [ -f "/usr/lib/i386-linux-gnu/libssl.so" ] ); then
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "!!! HEY YOU THERE, READING THE TGS LOGS READ THIS!!!"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "We are about to try installing native dependencies, we will use 'sudo' if possible for this, but it may fail because the tgstation-server user doesn't have passwordless sudo."
echo "WE DO NOT RECOMMEND GRANTING PASSWORDLESS SUDO!!! Instead, install all the dependencies yourself with the following command:"
echo ".................................................................................................................................................."
echo "sudo apt-get install -y lib32z1 git pkg-config libssl-dev:i386 libssl-dev zlib1g-dev:i386 curl libclang-dev g++-multilib python3 python3-pip unzip"
echo ".................................................................................................................................................."
echo "Attempting to install apt dependencies..."
if ! [ -x "$has_sudo" ]; then
dpkg --add-architecture i386
apt-get update
apt-get install -y lib32z1 git pkg-config libssl-dev:i386 libssl-dev zlib1g-dev:i386 curl
apt-get install -y lib32z1 git pkg-config libssl-dev:i386 libssl-dev zlib1g-dev:i386 curl libclang-dev g++-multilib python3 python3-pip unzip
else
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y lib32z1 git pkg-config libssl-dev:i386 libssl-dev zlib1g-dev:i386 curl
sudo apt-get install -y lib32z1 git pkg-config libssl-dev:i386 libssl-dev zlib1g-dev:i386 curl libclang-dev g++-multilib python3 python3-pip unzip
fi
fi
@@ -31,3 +40,13 @@ if ! [ -x "$has_cargo" ]; then
curl https://sh.rustup.rs -sSf | sh -s -- -y
. ~/.profile
fi
# install or update yt-dlp when not present, or if it is present with pip3,
# which we assume was used to install it
if ! [ -x "$has_ytdlp" ]; then
echo "Installing yt-dlp with pip3..."
pip3 install yt-dlp --break-system-packages
else
echo "Ensuring yt-dlp is up-to-date with pip3..."
pip3 install yt-dlp -U --break-system-packages
fi
+1 -10
View File
@@ -1,15 +1,6 @@
@echo off
cd /D "%~dp0"
set TG_BOOTSTRAP_CACHE=%cd%
IF NOT %1 == "" (
rem TGS4+: we are passed the game directory on the command line
cd %1
) ELSE IF EXIST "..\Game\B\tgstation.dmb" (
rem TGS3: Game/B/tgstation.dmb exists, so build in Game/A
cd ..\Game\A
) ELSE (
rem TGS3: Otherwise build in Game/B
cd ..\Game\B
)
cd %1
set CBT_BUILD_MODE=TGS
tools\build\build
+22 -1
View File
@@ -32,7 +32,28 @@ env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --ignore-rust-version --re
mv target/i686-unknown-linux-gnu/release/librust_g.so "$1/librust_g.so"
cd ..
#
cd "$original_dir"
# update dreamluau
if [ ! -d "dreamluau" ]; then
echo "Cloning dreamluau..."
git clone https://github.com/tgstation/dreamluau
cd dreamluau
~/.cargo/bin/rustup target add i686-unknown-linux-gnu
else
echo "Fetching dreamlaua..."
cd dreamluau
git fetch
~/.cargo/bin/rustup target add i686-unknown-linux-gnu
fi
echo "Deploying Dreamlaua..."
git checkout "$DREAMLUAU_VERSION"
env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --ignore-rust-version --release --target=i686-unknown-linux-gnu
mv target/i686-unknown-linux-gnu/release/libdreamluau.so "$1/libdreamluau.so"
cd ..
# compile tgui
echo "Compiling tgui..."
cd "$1"
env TG_BOOTSTRAP_CACHE="$original_dir" TG_BOOTSTRAP_NODE_LINUX=1 CBT_BUILD_MODE="TGS" tools/bootstrap/node tools/build/build.js
env TG_BOOTSTRAP_CACHE="$original_dir" CBT_BUILD_MODE="TGS" tools/bootstrap/javascript.sh tools/build/build.js
+2 -2
View File
@@ -1,4 +1,4 @@
// Simple app meant to test chompstation's TGS integration given a fresh TGS install with the default account
// Simple app meant to test tgstation's TGS integration given a fresh TGS install with the default account
//
// Args: Repository Owner/Name, TGS instance path, TGS API port, Pushed commit hash (For .tgs.yml access), GitHub Token, (OPTIONAL) PR Number
@@ -176,7 +176,7 @@ try
new InstanceCreateRequest
{
ConfigurationType = ConfigurationType.HostWrite,
Name = "chompstation",
Name = "tgstation",
Path = instancePath
},
default);
+2 -2
View File
@@ -7,5 +7,5 @@ This is a simple app that does a few things
- Connects to a TGS instance via command line parameters.
- Uses the .tgs.yml information to automatically set up a TGS instance.
- Runs a TGS deploy/launch and validates that they succeeded.
Look for its invocation in the GitHub workflows
Look for its invocation in the GitHub workflows
+2
View File
@@ -4528,6 +4528,8 @@
#include "code\modules\tgchat\message.dm"
#include "code\modules\tgchat\to_chat.dm"
#include "code\modules\tgs\includes.dm"
#include "code\modules\tgs_commands\chompstation.dm"
#include "code\modules\tgs_commands\vorestation.dm"
#include "code\modules\tgui\external.dm"
#include "code\modules\tgui\modal.dm"
#include "code\modules\tgui\states.dm"