Files
Aurora.3/code/controllers/subsystems/processing/tgui.dm
Matt Atlas 31956c7eb0 Rock the UI Away - Removes VueUI and adds TGUI (#16509)
* tgui the beginning

* binaries and the like

* Bring in the last of it

* Example radio UI

* delete example

* NTOS Main Menu, start on manifest, tgui states

* tasks.json

* gunnery ui pt 1

* okay

* fix everything

* scss update

* oops

* manifest gigablast

* downloader part 1

* download prt 2

* NTOSDownloader final

* mfw committing to_worlds

* gunnery console pt2

* i cooked

* targeting (finished)

* one vueui down

* voting ui almost done

* MY MIND FEELS LIKE AN ARCH ENEMYYYY

* voting ui down

* photocopier

* ntos config + download fixes

* photocopier 2

* refactor define

* NTOS client manager + fixes

* fax machine final (it also uses toner now)

* marching forwards... left behind...

* ntnrc part 1

* canister

* add quotes

* portable pumps pt1 + more backgrounds

* oops

* finish the portable pump

* freezers

so I'll keep on pushing forward... you haven't seen the last of me... oooooooh...

* doors ui pt1

* finish doors UI (forgive me wildkins it's a bit of shitcode)

* vitals monitor, make things use labeled lists, new backgrounds

* mais j'envoyé aucun mayday...

* maglock pt1

* pour ça je me suis perdu...

* infrared

* fix that

* prox sensor pt1

* prox sensor

* signaler (this was actually pretty hard)

* atmos control pt1

* atmos control pt1.1

* atmos pt 2

* fuel injector

* multitool UI

* jammer

* list viewer

* APC

* portgen

* targeting console updates + SMES ui

* new themes, shield generator

* supermatter

* Add ore detector and (shitty) NTNet Relay

* orderterminal pt1

* orderterminal pt2

* smartfridge

* Add (air-)tank GUI update ore detector size

* Adds Transfer Valves

* Add AtmoScrubber

* analyzer pt1

* weapons analyzer pt2

* bodyscanner pt1

* bodyscanner pt2

* fix this shitcode

* seed storage

* appearance changer

* appearance changer final

* sleeper pt1

* sleeper

* gps

* vehicles

* chem dispenser

* lily request

* holopad

* tgui modules pt1

* ppanel

* damage menu

* fixes

* im here too now

* follow menu, search bars

* quikpay

* quikpay fixes

* circuit printer

* ppanel

* ppanel updates

* pai

* turret controls (i want to kill myself)

* tweak

* remove the boardgame

* guntracker

* implant tracker

* penal mechs

come close to me, come close to me

* chem codex

* pai radio

* doorjack

* pai directives

* signaler removal, sensors

* ghost spawner

* spawnpoint

* fixes

* teleporter

* one more to the chopping block

* account database

* remove divider

* scanner, atmos

* latejoin ui pt1

* latejoin

* records pt1

* RECORDS UI DONE

* delete interpreter & records

* CHAT FUCKING CLIENT

* data updates

* fix some things

* final UI, log

* basic nanoui fix

* antag panel

* remove vueui

* atm update

* vending update

* warrants, cameras

* ntmonitor

* time comes for all

* preserve this legacy

* bring that back (oops)

* rcon, ui auto update for computer UIs, remove rcon computers

* alarm monitoring (a bit broke and also todo: add custom alarm monitoring programs to a few consoles)

* A LIKE SUPREME

* a

* power monitor

* lights on

* fuck this code, fuck nanoui modules, and fuck nanoui

* LEAVE IT OH SO FAR BEHIND

* fix alarm monitoring for synths

* I SAW IN YOU WHAT LIFE WAS MISSING

* comms console

* idcard and record updates

* turn the light on

* arcade

* pt2

* news browser

* static

* crusher

* f

* COULD I JUST SLEIGH THE GOLD FROM THE BALLS? I'M SO FRUSTRATED OH COULD YOU TELL? IF I HEAR ONE MORE VUEUI OR ONE NANOUI I'M GONNA LOSE IT SO LET ME GOOOOOOOOOOOOOOOOO

* codeowners & suit sensors

* html ui style removal

* make lint happy

* resist and disorder

* i slowly get up and turn off the noise, already fed up...

* pleaseeeeeeeeeeeeeee

* THE CREDIT LARP IS NECESSARY

* i hold the keys

* RISE UP

* fix that?

* harry's suggestions xoxo

* runtime fix pt2

* You are the only thing that I still care about

* adds build workflow

* Update update_tgui.yml

* adds some needed steps

* ATM

* misc fixes and tweaks

* fixes 2

* make newscasters usable and fix use power on freezers

* turret control is clearer

---------

Co-authored-by: John Wildkins <john.wildkins@gmail.com>
Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
Co-authored-by: Werner <Arrow768@users.noreply.github.com>
Co-authored-by: Geeves <ggrobler447@gmail.com>
Co-authored-by: harryob <me@harryob.live>
2023-06-25 19:03:33 +02:00

365 lines
9.9 KiB
Plaintext

/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
/**
* tgui subsystem
*
* Contains all tgui state and subsystem code.
*
*/
var/datum/controller/subsystem/processing/tgui/SStgui
/datum/controller/subsystem/processing/tgui
name = "tgui"
wait = 9
flags = SS_NO_INIT
priority = SS_PRIORITY_NANOUI
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
/// A list of UIs scheduled to process
var/list/current_run = list()
/// A list of open UIs
var/list/open_uis = list()
/// A list of open UIs, grouped by src_object.
var/list/open_uis_by_src = list()
/// The HTML base used for all UIs.
var/basehtml
/datum/controller/subsystem/processing/tgui/New()
NEW_SS_GLOBAL(SStgui)
basehtml = file2text('tgui/public/tgui.html')
// Inject inline polyfills
var/polyfill = file2text('tgui/public/tgui-polyfill.min.js')
polyfill = "<script>\n[polyfill]\n</script>"
basehtml = replacetextEx(basehtml, "<!-- tgui:inline-polyfill -->", polyfill)
basehtml = replacetextEx(basehtml, "<!-- tgui:nt-copyright -->", "NanoTrasen © 2457-[text2num(time2text(world.realtime, "YYYY")) + 442]")
/datum/controller/subsystem/processing/tgui/Shutdown()
close_all_uis()
/datum/controller/subsystem/processing/tgui/stat_entry(msg)
msg = "P:[length(open_uis)]"
return ..()
/datum/controller/subsystem/processing/tgui/fire(resumed = FALSE)
if(!resumed)
src.current_run = open_uis.Copy()
// Cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
while(current_run.len)
var/datum/tgui/ui = current_run[current_run.len]
current_run.len--
// TODO: Move user/src_object check to process()
if(ui?.user && ui.src_object)
ui.process(wait * 0.1)
else
open_uis.Remove(ui)
if(MC_TICK_CHECK)
return
/**
* public
*
* Requests a usable tgui window from the pool.
* Returns null if pool was exhausted.
*
* required user mob
* return datum/tgui
*/
/datum/controller/subsystem/processing/tgui/proc/request_pooled_window(mob/user)
if(!user.client)
return null
var/list/windows = user.client.tgui_windows
var/window_id
var/datum/tgui_window/window
var/window_found = FALSE
// Find a usable window
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
window_id = TGUI_WINDOW_ID(i)
window = windows[window_id]
// As we are looping, create missing window datums
if(!window)
window = new(user.client, window_id, pooled = TRUE)
// Skip windows with acquired locks
if(window.locked)
continue
if(window.status == TGUI_WINDOW_READY)
return window
if(window.status == TGUI_WINDOW_CLOSED)
window.status = TGUI_WINDOW_LOADING
window_found = TRUE
break
if(!window_found)
log_tgui(user, "Error: Pool exhausted",
context = "SStgui/request_pooled_window")
return null
return window
/**
* public
*
* Force closes all tgui windows.
*
* required user mob
*/
/datum/controller/subsystem/processing/tgui/proc/force_close_all_windows(mob/user)
log_tgui(user, context = "SStgui/force_close_all_windows")
if(user.client)
user.client.tgui_windows = list()
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
var/window_id = TGUI_WINDOW_ID(i)
user << browse(null, "window=[window_id]")
/**
* public
*
* Force closes the tgui window by window_id.
*
* required user mob
* required window_id string
*/
/datum/controller/subsystem/processing/tgui/proc/force_close_window(mob/user, window_id)
log_tgui(user, context = "SStgui/force_close_window")
// Close all tgui datums based on window_id.
for(var/datum/tgui/ui in user.tgui_open_uis)
if(ui.window && ui.window.id == window_id)
ui.close(can_be_suspended = FALSE)
// Unset machine just to be sure.
user.unset_machine()
// Close window directly just to be sure.
user << browse(null, "window=[window_id]")
/**
* public
*
* Try to find an instance of a UI, and push an update to it.
*
* required user mob The mob who opened/is using the UI.
* required src_object datum The object/datum which owns the UI.
* optional ui datum/tgui The UI to be updated, if it exists.
* optional force_open bool If the UI should be re-opened instead of updated.
*
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/processing/tgui/proc/try_update_ui(
mob/user,
datum/src_object,
datum/tgui/ui)
// Look up a UI if it wasn't passed
if(isnull(ui))
ui = get_open_ui(user, src_object)
// Couldn't find a UI.
if(isnull(ui))
return null
ui.process_status()
// UI ended up with the closed status
// or is actively trying to close itself.
// FIXME: Doesn't actually fix the paper bug.
if(ui.status <= UI_CLOSE)
ui.close()
return null
ui.send_update()
return ui
/**
* public
*
* Get a open UI given a user and src_object.
*
* required user mob The mob who opened/is using the UI.
* required src_object datum The object/datum which owns the UI.
*
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/processing/tgui/proc/get_open_ui(mob/user, datum/src_object)
var/key = text_ref(src_object)
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return null
for(var/datum/tgui/ui in open_uis_by_src[key])
// Make sure we have the right user
if(ui.user == user)
return ui
return null
/**
* public
*
* Update all UIs attached to src_object.
*
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs updated.
*/
/datum/controller/subsystem/processing/tgui/proc/update_uis(datum/src_object)
var/count = 0
var/key = text_ref(src_object)
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.process(wait * 0.1, force = 1)
count++
return count
/**
* public
*
* Close all UIs attached to src_object.
*
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/processing/tgui/proc/close_uis(datum/src_object)
var/count = 0
var/key = text_ref(src_object)
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
* public
*
* Close all UIs regardless of their attachment to src_object.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/processing/tgui/proc/close_all_uis()
var/count = 0
for(var/key in open_uis_by_src)
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
* public
*
* Update all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object datum If provided, only update UIs belonging this src_object.
*
* return int The number of UIs updated.
*/
/datum/controller/subsystem/processing/tgui/proc/update_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
ui.process(wait * 0.1, force = 1)
count++
return count
/**
* public
*
* Close all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object datum If provided, only close UIs belonging this src_object.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/processing/tgui/proc/close_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
ui.close()
count++
return count
/**
* private
*
* Add a UI to the list of open UIs.
*
* required ui datum/tgui The UI to be added.
*/
/datum/controller/subsystem/processing/tgui/proc/on_open(datum/tgui/ui)
var/key = text_ref(ui.src_object)
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
open_uis_by_src[key] = list()
ui.user.tgui_open_uis |= ui
var/list/uis = open_uis_by_src[key]
uis |= ui
open_uis |= ui
/**
* private
*
* Remove a UI from the list of open UIs.
*
* required ui datum/tgui The UI to be removed.
*
* return bool If the UI was removed or not.
*/
/datum/controller/subsystem/processing/tgui/proc/on_close(datum/tgui/ui)
var/key = text_ref(ui.src_object)
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return FALSE
// Remove it from the list of processing UIs.
open_uis.Remove(ui)
// If the user exists, remove it from them too.
if(ui.user)
ui.user.tgui_open_uis.Remove(ui)
var/list/uis = open_uis_by_src[key]
uis.Remove(ui)
if(length(uis) == 0)
open_uis_by_src.Remove(key)
return TRUE
/**
* private
*
* Handle client logout, by closing all their UIs.
*
* required user mob The mob which logged out.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/processing/tgui/proc/on_logout(mob/user)
close_user_uis(user)
/**
* private
*
* Handle clients switching mobs, by transferring their UIs.
*
* required user source The client's original mob.
* required user target The client's new mob.
*
* return bool If the UIs were transferred.
*/
/datum/controller/subsystem/processing/tgui/proc/on_transfer(mob/source, mob/target)
// The old mob had no open UIs.
if(length(source?.tgui_open_uis) == 0)
return FALSE
if(isnull(target.tgui_open_uis) || !istype(target.tgui_open_uis, /list))
target.tgui_open_uis = list()
// Transfer all the UIs.
for(var/datum/tgui/ui in source.tgui_open_uis)
// Inform the UIs of their new owner.
ui.user = target
target.tgui_open_uis.Add(ui)
// Clear the old list.
source.tgui_open_uis.Cut()
return TRUE