Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions code/controllers/configuration/entries/general.dm
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,10 @@
/datum/config_entry/string/elasticsearch_metrics_endpoint

/datum/config_entry/string/elasticsearch_metrics_apikey

/**
* Tgui ui_act payloads larger than 2kb are split into chunks a maximum of 1kb in size.
* This flag represents the maximum chunk count the server is willing to receive.
*/
/datum/config_entry/number/tgui_max_chunk_count
default = 32
48 changes: 44 additions & 4 deletions code/modules/tgui/tgui_window.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
var/initial_inline_css
var/mouse_event_macro_set = FALSE

var/list/oversized_payloads = list()

/**
* public
*
Expand Down Expand Up @@ -356,11 +358,18 @@
if("openLink")
client << link(href_list["url"])
if("cacheReloaded")
// Reinitialize
reinitialize()
// Resend the assets
for(var/asset in sent_assets)
send_asset(asset)
if("oversizedPayloadRequest")
var/payload_id = payload["id"]
var/chunk_count = payload["chunkCount"]
var/permit_payload = chunk_count <= CONFIG_GET(number/tgui_max_chunk_count)
if(permit_payload)
create_oversized_payload(payload_id, payload["type"], chunk_count)
send_message("oversizePayloadResponse", list("allow" = permit_payload, "id" = payload_id))
if("payloadChunk")
var/payload_id = payload["id"]
append_payload_chunk(payload_id, payload["chunk"])
send_message("acknowlegePayloadChunk", list("id" = payload_id))

/datum/tgui_window/proc/set_mouse_macro()
if(mouse_event_macro_set)
Expand Down Expand Up @@ -398,3 +407,34 @@
for(var/mouseMacro in byondToTguiEventMap)
winset(client, null, "[mouseMacro]Window[id]Macro.parent=null")
mouse_event_macro_set = FALSE

/datum/tgui_window/vv_edit_var(var_name, var_value)
return var_name != NAMEOF(src, id) && ..()

/datum/tgui_window/proc/create_oversized_payload(payload_id, message_type, chunk_count)
if(oversized_payloads[payload_id])
CRASH("Attempted to create oversized tgui payload with duplicate ID.")
oversized_payloads[payload_id] = list(
"type" = message_type,
"count" = chunk_count,
"chunks" = list(),
"timeout" = addtimer(CALLBACK(src, PROC_REF(remove_oversized_payload), payload_id), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)
)

/datum/tgui_window/proc/append_payload_chunk(payload_id, chunk)
var/list/payload = oversized_payloads[payload_id]
if(!payload)
return
var/list/chunks = payload["chunks"]
chunks += chunk
if(length(chunks) >= payload["count"])
deltimer(payload["timeout"])
var/message_type = payload["type"]
var/final_payload = chunks.Join()
remove_oversized_payload(payload_id)
on_message(message_type, json_decode(final_payload), list("type" = message_type, "payload" = final_payload, "tgui" = TRUE, "window_id" = id))
else
payload["timeout"] = addtimer(CALLBACK(src, PROC_REF(remove_oversized_payload), payload_id), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)

/datum/tgui_window/proc/remove_oversized_payload(payload_id)
oversized_payloads -= payload_id
6 changes: 2 additions & 4 deletions code/modules/tgui_panel/external.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
tgui_panel = new(src)
tgui_panel.initialize(force = TRUE)
// Force show the panel to see if there are any errors
winset(src, "output", "is-disabled=1&is-visible=0")
winset(src, "browseroutput", "is-disabled=0;is-visible=1")
winset(src, "legacy_output_selector", "left=output_browser")
action = alert(src, "Method: Reinitializing the panel.\nWait a bit and tell me if it's fixed", "", "Fixed", "Nope")
if(action == "Fixed")
log_tgui(src, "Fixed by calling 'initialize'",
Expand All @@ -41,7 +40,6 @@
// Failed to fix
action = alert(src, "Welp, I'm all out of ideas. Try closing BYOND and reconnecting.\nWe could also disable tgui_panel and re-enable the old UI", "", "Thanks anyways", "Switch to old UI")
if (action == "Switch to old UI")
winset(src, "output", "on-show=&is-disabled=0&is-visible=1")
winset(src, "browseroutput", "is-disabled=1;is-visible=0")
winset(src, "legacy_output_selector", "left=output_legacy")
log_tgui(src, "Failed to fix.",
context = "verb/fix_tgui_panel")
4 changes: 4 additions & 0 deletions config/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,7 @@ ELASTICSEARCH_METRICS_ENDPOINT http://10.0.0.40:9201/ss13-metrics-stream/_doc

## ElasticSearch API key. This is formatted into the headers. Look at the ElasticSearch doc for how to make this
ELASTICSEARCH_METRICS_APIKEY thisIsSomethingThatsBased64Encoded==

## Tgui payloads larger than the 2kb limit for BYOND topic requests are split into roughly 1kb chunks and sent in sequence.
## This config option limits the maximum chunk count for which the server will accept a payload, default is 32
TGUI_MAX_CHUNK_COUNT 32
38 changes: 32 additions & 6 deletions interface/skin.dmf
Original file line number Diff line number Diff line change
Expand Up @@ -292,16 +292,25 @@ window "outputwindow"
text = "Me"
command = ".winset \"mebutton.is-checked=true ? input.command=\"!me \\\"\" : input.command=\"\"mebutton.is-checked=true ? saybutton.is-checked=false\"\"mebutton.is-checked=true ? oocbutton.is-checked=false\""
button-type = pushbox
elem "browseroutput"
type = BROWSER
elem "legacy_output_selector"
type = CHILD
pos = 0,0
size = 640x456
anchor1 = 0,0
anchor2 = 100,100
background-color = #ffffff
is-visible = false
is-disabled = true
saved-params = ""
saved-params = "splitter"
left = "output_legacy"
is-vert = false

window "output_legacy"
elem "output_legacy"
type = MAIN
pos = 0,0
size = 640x456
anchor1 = -1,-1
anchor2 = -1,-1
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "output"
type = OUTPUT
pos = 0,0
Expand All @@ -311,6 +320,23 @@ window "outputwindow"
is-default = true
saved-params = ""

window "output_browser"
elem "output_browser"
type = MAIN
pos = 0,0
size = 640x456
anchor1 = -1,-1
anchor2 = -1,-1
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "browseroutput"
type = BROWSER
pos = 0,0
size = 640x456
anchor1 = 0,0
anchor2 = 100,100
saved-params = ""

window "popupwindow"
elem "popupwindow"
type = MAIN
Expand Down
5 changes: 5 additions & 0 deletions tgui/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ type ByondType = {
*/
parseJson(text: string): any;

/**
* Downloads a blob, platform-agnostic
*/
saveBlob(blob: Blob, filename: string, ext: string): void;

/**
* Sends a message to `/datum/tgui_window` which hosts this window instance.
*/
Expand Down
2 changes: 1 addition & 1 deletion tgui/packages/tgui-panel/chat/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ class ChatRenderer {
+ '</body>\n'
+ '</html>\n';
// Create and send a nice blob
const blob = new Blob([pageHtml]);
const blob = new Blob([pageHtml], { type: 'text/plain' });
const timestamp = new Date()
.toISOString()
.substring(0, 19)
Expand Down
10 changes: 2 additions & 8 deletions tgui/packages/tgui-panel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,8 @@ const setupApp = () => {
Byond.subscribe((type, payload) => store.dispatch({ type, payload }));

// Unhide the panel
Byond.winset('output', {
'is-visible': false,
});
Byond.winset('browseroutput', {
'is-visible': true,
'is-disabled': false,
'pos': '0x0',
'size': '0x0',
Byond.winset('legacy_output_selector', {
left: 'output_browser',
});

// Resize the panel to match the non-browser output
Expand Down
Loading
Loading