mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-08-27 23:29:10 +01:00
[Manual MIRROR] dmapi manual update port (#11138)
This commit is contained in:
@@ -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 }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
Vendored
+7
-7
@@ -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",
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]),
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
+12
@@ -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)]```"
|
||||
@@ -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)
|
||||
|
||||
@@ -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."))
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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%),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
config.json
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"port": 6969,
|
||||
"token": "your-token-goes-here",
|
||||
"guildId": "your-guild-snowflake-goes-here",
|
||||
"roleId": "your-role-snowflake-goes-here"
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user