mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 02:09:41 +00:00
[MIRROR] split tgui html (#10594)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
5383e18a48
commit
dd0ab1d10c
@@ -26,6 +26,17 @@ SUBSYSTEM_DEF(tgui)
|
||||
|
||||
/datum/controller/subsystem/tgui/PreInit()
|
||||
basehtml = file2text('tgui/public/tgui.html')
|
||||
|
||||
// Inject inline helper functions
|
||||
var/helpers = file2text('tgui/public/helpers.min.js')
|
||||
helpers = "<script type='text/javascript'>\n[helpers]\n</script>"
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:helpers -->", helpers)
|
||||
|
||||
// Inject inline ntos-error styles
|
||||
var/ntos_error = file2text('tgui/public/ntos-error.min.css')
|
||||
ntos_error = "<style type='text/css'>\n[ntos_error]\n</style>"
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:ntos-error -->", ntos_error)
|
||||
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:nt-copyright -->", "Nanotrasen (c) 2284-[CURRENT_STATION_YEAR]")
|
||||
|
||||
/datum/controller/subsystem/tgui/Shutdown()
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
var/atom/movable/AM = WF.resolve()
|
||||
if(isnull(AM))
|
||||
log_debug("DEBUG: HasProximity called without reference on [src].")
|
||||
attached_device?.HasProximity(T, WEAKREF(AM), old_loc)
|
||||
attached_device?.HasProximity(T, WF, old_loc)
|
||||
|
||||
/obj/item/transfer_valve/Moved(old_loc, direction, forced)
|
||||
. = ..()
|
||||
|
||||
@@ -661,11 +661,11 @@ var/list/global/tank_gauge_cache = list()
|
||||
SIGNAL_HANDLER
|
||||
if(isnull(WF))
|
||||
return
|
||||
var/atom/movable/AM = WF
|
||||
var/atom/movable/AM = WF.resolve()
|
||||
if(isnull(AM))
|
||||
log_debug("DEBUG: HasProximity called without reference on [src].")
|
||||
return
|
||||
assembly?.HasProximity(T, WEAKREF(AM), old_loc)
|
||||
assembly?.HasProximity(T, WF, old_loc)
|
||||
|
||||
/obj/item/tankassemblyproxy/Moved(old_loc, direction, forced)
|
||||
if(isturf(old_loc))
|
||||
|
||||
@@ -79,9 +79,9 @@
|
||||
log_debug("DEBUG: HasProximity called without reference on [src].")
|
||||
return
|
||||
if(a_left)
|
||||
a_left.HasProximity(T, AM, old_loc)
|
||||
a_left.HasProximity(T, WF, old_loc)
|
||||
if(a_right)
|
||||
a_right.HasProximity(T, AM, old_loc)
|
||||
a_right.HasProximity(T, WF, old_loc)
|
||||
|
||||
/obj/item/assembly_holder/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
|
||||
@@ -82,10 +82,7 @@
|
||||
return
|
||||
if(L.devourable && L.allowmobvore && (src.vore_fullness < src.vore_capacity))
|
||||
perform_the_nom(src,L,src,src.vore_selected,1)
|
||||
L |= eaten_mobs
|
||||
return
|
||||
else
|
||||
return
|
||||
eaten_mobs += L
|
||||
|
||||
|
||||
////////////////////////////PITCHER PLANT////////////////////////////////////////////////
|
||||
|
||||
2
tgui/.gitignore
vendored
2
tgui/.gitignore
vendored
@@ -16,6 +16,8 @@ package-lock.json
|
||||
/public/.tmp/**/*
|
||||
/public/**/*
|
||||
!/public/*.html
|
||||
!/public/ntos-error.min.css
|
||||
!/public/helpers.min.js
|
||||
/coverage
|
||||
|
||||
## Previously ignored locations that are kept to avoid confusing git
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
.swcrc
|
||||
/docs
|
||||
/public
|
||||
/packages/tgui-polyfill
|
||||
/packages/tgfont/static
|
||||
/packages/tgfont/dist
|
||||
@@ -16,6 +15,7 @@
|
||||
**/*.yml
|
||||
**/*.md
|
||||
|
||||
## Build artifacts
|
||||
/public/.tmp/**/*
|
||||
/public/*.map
|
||||
# Avoid running on any bundles.
|
||||
/public/**/*
|
||||
# Running it on tgui.html is fine, however.
|
||||
!/public/tgui.html
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
singleQuote: true
|
||||
overrides:
|
||||
- files: 'packages/tgui-setup/helpers.js'
|
||||
options:
|
||||
trailingComma: es5
|
||||
arrowParens: always
|
||||
|
||||
20
tgui/.yarn/sdks/eslint/bin/eslint.js
vendored
20
tgui/.yarn/sdks/eslint/bin/eslint.js
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/bin/eslint.js
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/bin/eslint.js your application uses
|
||||
module.exports = absRequire(`eslint/bin/eslint.js`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/bin/eslint.js`));
|
||||
|
||||
20
tgui/.yarn/sdks/eslint/lib/api.js
vendored
20
tgui/.yarn/sdks/eslint/lib/api.js
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint your application uses
|
||||
module.exports = absRequire(`eslint`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint`));
|
||||
|
||||
22
tgui/.yarn/sdks/eslint/lib/unsupported-api.js
vendored
22
tgui/.yarn/sdks/eslint/lib/unsupported-api.js
vendored
@@ -1,20 +1,32 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/use-at-your-own-risk
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/use-at-your-own-risk your application uses
|
||||
module.exports = absRequire(`eslint/use-at-your-own-risk`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/use-at-your-own-risk`));
|
||||
|
||||
2
tgui/.yarn/sdks/eslint/package.json
vendored
2
tgui/.yarn/sdks/eslint/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eslint",
|
||||
"version": "8.57.0-sdk",
|
||||
"version": "8.57.1-sdk",
|
||||
"main": "./lib/api.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
|
||||
20
tgui/.yarn/sdks/prettier/bin/prettier.cjs
vendored
20
tgui/.yarn/sdks/prettier/bin/prettier.cjs
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require prettier/bin/prettier.cjs
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real prettier/bin/prettier.cjs your application uses
|
||||
module.exports = absRequire(`prettier/bin/prettier.cjs`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`prettier/bin/prettier.cjs`));
|
||||
|
||||
20
tgui/.yarn/sdks/prettier/index.cjs
vendored
20
tgui/.yarn/sdks/prettier/index.cjs
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require prettier
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real prettier your application uses
|
||||
module.exports = absRequire(`prettier`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`prettier`));
|
||||
|
||||
2
tgui/.yarn/sdks/prettier/package.json
vendored
2
tgui/.yarn/sdks/prettier/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "prettier",
|
||||
"version": "3.2.5-sdk",
|
||||
"version": "3.5.3-sdk",
|
||||
"main": "./index.cjs",
|
||||
"type": "commonjs",
|
||||
"bin": "./bin/prettier.cjs"
|
||||
|
||||
20
tgui/.yarn/sdks/typescript/bin/tsc
vendored
20
tgui/.yarn/sdks/typescript/bin/tsc
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/bin/tsc
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/bin/tsc your application uses
|
||||
module.exports = absRequire(`typescript/bin/tsc`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsc`));
|
||||
|
||||
20
tgui/.yarn/sdks/typescript/bin/tsserver
vendored
20
tgui/.yarn/sdks/typescript/bin/tsserver
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/bin/tsserver
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/bin/tsserver your application uses
|
||||
module.exports = absRequire(`typescript/bin/tsserver`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsserver`));
|
||||
|
||||
20
tgui/.yarn/sdks/typescript/lib/tsc.js
vendored
20
tgui/.yarn/sdks/typescript/lib/tsc.js
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsc.js
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/lib/tsc.js your application uses
|
||||
module.exports = absRequire(`typescript/lib/tsc.js`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/lib/tsc.js`));
|
||||
|
||||
43
tgui/.yarn/sdks/typescript/lib/tsserver.js
vendored
43
tgui/.yarn/sdks/typescript/lib/tsserver.js
vendored
@@ -1,15 +1,48 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
<<<<<<< HEAD
|
||||
const moduleWrapper = (tsserver) => {
|
||||
=======
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsserver.js
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
const moduleWrapper = exports => {
|
||||
return wrapWithUserWrapper(moduleWrapperFn(exports));
|
||||
};
|
||||
|
||||
const moduleWrapperFn = tsserver => {
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
@@ -261,11 +294,11 @@ const moduleWrapper = (tsserver) => {
|
||||
return tsserver;
|
||||
};
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsserver.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10));
|
||||
// In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well.
|
||||
// Ref https://github.com/microsoft/TypeScript/pull/55326
|
||||
if (major > 5 || (major === 5 && minor >= 5)) {
|
||||
moduleWrapper(absRequire(`typescript`));
|
||||
}
|
||||
|
||||
// Defer to the real typescript/lib/tsserver.js your application uses
|
||||
|
||||
@@ -1,15 +1,48 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
<<<<<<< HEAD
|
||||
const moduleWrapper = (tsserver) => {
|
||||
=======
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
const moduleWrapper = exports => {
|
||||
return wrapWithUserWrapper(moduleWrapperFn(exports));
|
||||
};
|
||||
|
||||
const moduleWrapperFn = tsserver => {
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
@@ -261,11 +294,11 @@ const moduleWrapper = (tsserver) => {
|
||||
return tsserver;
|
||||
};
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10));
|
||||
// In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well.
|
||||
// Ref https://github.com/microsoft/TypeScript/pull/55326
|
||||
if (major > 5 || (major === 5 && minor >= 5)) {
|
||||
moduleWrapper(absRequire(`typescript`));
|
||||
}
|
||||
|
||||
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
|
||||
|
||||
20
tgui/.yarn/sdks/typescript/lib/typescript.js
vendored
20
tgui/.yarn/sdks/typescript/lib/typescript.js
vendored
@@ -1,20 +1,38 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
<<<<<<< HEAD
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
=======
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
>>>>>>> cc02a1a056 (split tgui html (#17476))
|
||||
|
||||
const relPnpApiPath = '../../../../.pnp.cjs';
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require typescript
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript your application uses
|
||||
module.exports = absRequire(`typescript`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript`));
|
||||
|
||||
573
tgui/packages/tgui-setup/helpers.js
Normal file
573
tgui/packages/tgui-setup/helpers.js
Normal file
@@ -0,0 +1,573 @@
|
||||
/* eslint-disable */
|
||||
|
||||
(function () {
|
||||
// Utility functions
|
||||
let hasOwn = Object.prototype.hasOwnProperty;
|
||||
let assign = function (target) {
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
let source = arguments[i];
|
||||
for (let key in source) {
|
||||
if (hasOwn.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
let parseMetaTag = function (name) {
|
||||
let content = document.getElementById(name).getAttribute('content');
|
||||
if (content === '[' + name + ']') {
|
||||
return null;
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
// BYOND API object
|
||||
// ------------------------------------------------------
|
||||
|
||||
let Byond = (window.Byond = {});
|
||||
|
||||
// Expose inlined metadata
|
||||
Byond.windowId = parseMetaTag('tgui:windowId');
|
||||
|
||||
// Backwards compatibility
|
||||
window.__windowId__ = Byond.windowId;
|
||||
|
||||
// Trident engine version
|
||||
Byond.TRIDENT = (function () {
|
||||
let groups = navigator.userAgent.match(/Trident\/(\d+).+?;/i);
|
||||
let majorVersion = groups && groups[1];
|
||||
return majorVersion ? parseInt(majorVersion, 10) : null;
|
||||
})();
|
||||
|
||||
// Blink engine version
|
||||
Byond.BLINK = (function () {
|
||||
let groups = navigator.userAgent.match(/Chrome\/(\d+)\./);
|
||||
let majorVersion = groups && groups[1];
|
||||
return majorVersion ? parseInt(majorVersion, 10) : null;
|
||||
})();
|
||||
|
||||
// Basic checks to detect whether this page runs in BYOND
|
||||
let isByond =
|
||||
(Byond.TRIDENT !== null || Byond.BLINK !== null || window.cef_to_byond) &&
|
||||
location.hostname === '127.0.0.1' &&
|
||||
location.search !== '?external';
|
||||
// As of BYOND 515 the path doesn't seem to include tmp dir anymore if you're trying to open tgui in external browser and looking why it doesn't work
|
||||
// && location.pathname.indexOf('/tmp') === 0
|
||||
|
||||
// Version constants
|
||||
Byond.IS_BYOND = isByond;
|
||||
|
||||
// Strict mode flag
|
||||
Byond.strictMode = Boolean(Number(parseMetaTag('tgui:strictMode')));
|
||||
|
||||
// Callbacks for asynchronous calls
|
||||
Byond.__callbacks__ = [];
|
||||
|
||||
// Reviver for BYOND JSON
|
||||
let byondJsonReviver = function (key, value) {
|
||||
if (typeof value === 'object' && value !== null && value.__number__) {
|
||||
return parseFloat(value.__number__);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
// Makes a BYOND call.
|
||||
// See: https://secure.byond.com/docs/ref/skinparams.html
|
||||
Byond.call = function (path, params) {
|
||||
// Not running in BYOND, abort.
|
||||
if (!isByond) {
|
||||
return;
|
||||
}
|
||||
// Build the URL
|
||||
let url = (path || '') + '?';
|
||||
let i = 0;
|
||||
if (params) {
|
||||
for (let key in params) {
|
||||
if (hasOwn.call(params, key)) {
|
||||
if (i++ > 0) {
|
||||
url += '&';
|
||||
}
|
||||
let value = params[key];
|
||||
if (value === null || value === undefined) {
|
||||
value = '';
|
||||
}
|
||||
url += encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're a Chromium client, just use the fancy method
|
||||
if (window.cef_to_byond) {
|
||||
cef_to_byond('byond://' + url);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform a standard call via location.href
|
||||
if (url.length < 2048) {
|
||||
location.href = 'byond://' + url;
|
||||
return;
|
||||
}
|
||||
// Send an HTTP request to DreamSeeker's HTTP server.
|
||||
// Allows sending much bigger payloads.
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
Byond.callAsync = function (path, params) {
|
||||
if (!window.Promise) {
|
||||
throw new Error('Async calls require API level of ES2015 or later.');
|
||||
}
|
||||
let index = Byond.__callbacks__.length;
|
||||
let promise = new window.Promise((resolve) => {
|
||||
Byond.__callbacks__.push(resolve);
|
||||
});
|
||||
Byond.call(
|
||||
path,
|
||||
assign({}, params, {
|
||||
callback: 'Byond.__callbacks__[' + index + ']',
|
||||
})
|
||||
);
|
||||
return promise;
|
||||
};
|
||||
|
||||
Byond.topic = function (params) {
|
||||
return Byond.call('', params);
|
||||
};
|
||||
|
||||
Byond.command = function (command) {
|
||||
return Byond.call('winset', {
|
||||
command: command,
|
||||
});
|
||||
};
|
||||
|
||||
Byond.winget = function (id, propName) {
|
||||
if (id === null) {
|
||||
id = '';
|
||||
}
|
||||
let isArray = propName instanceof Array;
|
||||
let isSpecific = propName && propName !== '*' && !isArray;
|
||||
let promise = Byond.callAsync('winget', {
|
||||
id: id,
|
||||
property: (isArray && propName.join(',')) || propName || '*',
|
||||
});
|
||||
if (isSpecific) {
|
||||
promise = promise.then((props) => {
|
||||
return props[propName];
|
||||
});
|
||||
}
|
||||
return promise;
|
||||
};
|
||||
|
||||
Byond.winset = function (id, propName, propValue) {
|
||||
if (id === null) {
|
||||
id = '';
|
||||
} else if (typeof id === 'object') {
|
||||
return Byond.call('winset', id);
|
||||
}
|
||||
let props = {};
|
||||
if (typeof propName === 'string') {
|
||||
props[propName] = propValue;
|
||||
} else {
|
||||
assign(props, propName);
|
||||
}
|
||||
props.id = id;
|
||||
return Byond.call('winset', props);
|
||||
};
|
||||
|
||||
Byond.parseJson = function (json) {
|
||||
try {
|
||||
return JSON.parse(json, byondJsonReviver);
|
||||
} catch (err) {
|
||||
throw new Error('JSON parsing error: ' + (err && err.message));
|
||||
}
|
||||
};
|
||||
|
||||
let MAX_PACKET_SIZE = 1024;
|
||||
|
||||
Byond.sendMessage = function (type, payload) {
|
||||
let message =
|
||||
typeof type === 'string' ? { type: type, payload: payload } : type;
|
||||
// JSON-encode the payload
|
||||
|
||||
if (message.payload !== null && message.payload !== undefined) {
|
||||
message.payload = JSON.stringify(message.payload);
|
||||
|
||||
if (!Byond.TRIDENT && message.payload.length > MAX_PACKET_SIZE) {
|
||||
let chunks = [];
|
||||
|
||||
for (
|
||||
let i = 0, charsLength = message.payload.length;
|
||||
i < charsLength;
|
||||
i += MAX_PACKET_SIZE
|
||||
) {
|
||||
chunks.push(message.payload.substring(i, i + MAX_PACKET_SIZE));
|
||||
}
|
||||
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
let to_send = chunks[i];
|
||||
|
||||
message = {
|
||||
type: type,
|
||||
packet: to_send,
|
||||
packetId: i + 1,
|
||||
totalPackets: chunks.length,
|
||||
tgui: 1,
|
||||
window_id: Byond.windowId,
|
||||
};
|
||||
Byond.topic(message);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Append an identifying header
|
||||
assign(message, {
|
||||
tgui: 1,
|
||||
window_id: Byond.windowId,
|
||||
});
|
||||
Byond.topic(message);
|
||||
};
|
||||
|
||||
// This function exists purely for debugging, do not use it in code!
|
||||
Byond.injectMessage = function (type, payload) {
|
||||
window.update(JSON.stringify({ type: type, payload: payload }));
|
||||
};
|
||||
|
||||
Byond.subscribe = function (listener) {
|
||||
window.update.flushQueue(listener);
|
||||
window.update.listeners.push(listener);
|
||||
};
|
||||
|
||||
Byond.subscribeTo = function (type, listener) {
|
||||
let _listener = function (_type, payload) {
|
||||
if (_type === type) {
|
||||
listener(payload);
|
||||
}
|
||||
};
|
||||
window.update.flushQueue(_listener);
|
||||
window.update.listeners.push(_listener);
|
||||
};
|
||||
|
||||
// Asset loaders
|
||||
// ------------------------------------------------------
|
||||
|
||||
let RETRY_ATTEMPTS = 5;
|
||||
let RETRY_WAIT_INITIAL = 500;
|
||||
let RETRY_WAIT_INCREMENT = 500;
|
||||
|
||||
let loadedAssetByUrl = {};
|
||||
|
||||
let isStyleSheetLoaded = function (node, url) {
|
||||
let styleSheet = node.sheet;
|
||||
if (styleSheet) {
|
||||
return styleSheet.rules.length > 0;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
let injectNode = function (node) {
|
||||
if (!document.body) {
|
||||
setTimeout(() => {
|
||||
injectNode(node);
|
||||
});
|
||||
return;
|
||||
}
|
||||
let refs = document.body.childNodes;
|
||||
let ref = refs[refs.length - 1];
|
||||
ref.parentNode.insertBefore(node, ref.nextSibling);
|
||||
};
|
||||
|
||||
let loadAsset = function (options) {
|
||||
let url = options.url;
|
||||
let type = options.type;
|
||||
let sync = options.sync;
|
||||
let attempt = options.attempt || 0;
|
||||
if (loadedAssetByUrl[url]) {
|
||||
return;
|
||||
}
|
||||
loadedAssetByUrl[url] = options;
|
||||
// Generic retry function
|
||||
let retry = function () {
|
||||
if (attempt >= RETRY_ATTEMPTS) {
|
||||
let errorMessage =
|
||||
'Error: Failed to load the asset ' +
|
||||
"'" +
|
||||
url +
|
||||
"' after several attempts.";
|
||||
if (type === 'css') {
|
||||
errorMessage +=
|
||||
+'\nStylesheet was either not found, ' +
|
||||
"or you're trying to load an empty stylesheet " +
|
||||
'that has no CSS rules in it.';
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
setTimeout(
|
||||
() => {
|
||||
loadedAssetByUrl[url] = null;
|
||||
options.attempt += 1;
|
||||
loadAsset(options);
|
||||
},
|
||||
RETRY_WAIT_INITIAL + attempt * RETRY_WAIT_INCREMENT
|
||||
);
|
||||
};
|
||||
// JS specific code
|
||||
if (type === 'js') {
|
||||
let node = document.createElement('script');
|
||||
node.type = 'text/javascript';
|
||||
node.crossOrigin = 'anonymous';
|
||||
node.src = url;
|
||||
if (sync) {
|
||||
node.defer = true;
|
||||
} else {
|
||||
node.async = true;
|
||||
}
|
||||
node.onerror = function () {
|
||||
node.onerror = null;
|
||||
node.parentNode.removeChild(node);
|
||||
node = null;
|
||||
retry();
|
||||
};
|
||||
injectNode(node);
|
||||
return;
|
||||
}
|
||||
// CSS specific code
|
||||
if (type === 'css') {
|
||||
let node = document.createElement('link');
|
||||
node.type = 'text/css';
|
||||
node.rel = 'stylesheet';
|
||||
node.crossOrigin = 'anonymous';
|
||||
node.href = url;
|
||||
// Temporarily set media to something inapplicable
|
||||
// to ensure it'll fetch without blocking render
|
||||
if (!sync) {
|
||||
node.media = 'only x';
|
||||
}
|
||||
let removeNodeAndRetry = function () {
|
||||
node.parentNode.removeChild(node);
|
||||
node = null;
|
||||
retry();
|
||||
};
|
||||
// 516: Chromium won't call onload() if there is a 404 error
|
||||
// Legacy IE doesn't use onerror, so we retain that
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#stylesheet_load_events
|
||||
node.onerror = function () {
|
||||
node.onerror = null;
|
||||
removeNodeAndRetry();
|
||||
};
|
||||
node.onload = function () {
|
||||
node.onload = null;
|
||||
if (isStyleSheetLoaded(node, url)) {
|
||||
// Render the stylesheet
|
||||
node.media = 'all';
|
||||
return;
|
||||
}
|
||||
removeNodeAndRetry();
|
||||
};
|
||||
injectNode(node);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Byond.loadJs = function (url, sync) {
|
||||
loadAsset({ url: url, sync: sync, type: 'js' });
|
||||
};
|
||||
|
||||
Byond.loadCss = function (url, sync) {
|
||||
loadAsset({ url: url, sync: sync, type: 'css' });
|
||||
};
|
||||
|
||||
Byond.saveBlob = function (blob, filename, ext) {
|
||||
if (window.navigator.msSaveBlob) {
|
||||
window.navigator.msSaveBlob(blob, filename);
|
||||
} else if (window.showSaveFilePicker) {
|
||||
let accept = {};
|
||||
accept[blob.type] = [ext];
|
||||
|
||||
let opts = {
|
||||
suggestedName: filename,
|
||||
types: [
|
||||
{
|
||||
description: 'SS13 file',
|
||||
accept: accept,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
try {
|
||||
window
|
||||
.showSaveFilePicker(opts)
|
||||
.then((fileHandle) => {
|
||||
fileHandle
|
||||
.createWritable()
|
||||
.then((writeableFileHandle) => {
|
||||
writeableFileHandle
|
||||
.write(blob)
|
||||
.then(() => {
|
||||
writeableFileHandle.close();
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Icon cache
|
||||
Byond.iconRefMap = {};
|
||||
})();
|
||||
|
||||
// Error handling
|
||||
// ------------------------------------------------------
|
||||
|
||||
window.onerror = function (msg, url, line, col, error) {
|
||||
window.onerror.errorCount = (window.onerror.errorCount || 0) + 1;
|
||||
// Proper stacktrace
|
||||
let stack = error && error.stack;
|
||||
// Ghetto stacktrace
|
||||
if (!stack) {
|
||||
stack = msg + '\n at ' + url + ':' + line;
|
||||
if (col) {
|
||||
stack += ':' + col;
|
||||
}
|
||||
}
|
||||
// Augment the stack
|
||||
stack = window.__augmentStack__(stack, error);
|
||||
// Print error to the page
|
||||
if (Byond.strictMode) {
|
||||
let errorRoot = document.getElementById('FatalError');
|
||||
let errorStack = document.getElementById('FatalError__stack');
|
||||
if (errorRoot) {
|
||||
errorRoot.className = 'FatalError FatalError--visible';
|
||||
if (window.onerror.__stack__) {
|
||||
window.onerror.__stack__ += '\n\n' + stack;
|
||||
} else {
|
||||
window.onerror.__stack__ = stack;
|
||||
}
|
||||
let textProp = 'textContent';
|
||||
errorStack[textProp] = window.onerror.__stack__;
|
||||
}
|
||||
// Set window geometry
|
||||
let setFatalErrorGeometry = function () {
|
||||
Byond.winset(Byond.windowId, {
|
||||
titlebar: true,
|
||||
'is-visible': true,
|
||||
'can-resize': true,
|
||||
});
|
||||
};
|
||||
setFatalErrorGeometry();
|
||||
setInterval(setFatalErrorGeometry, 1000);
|
||||
}
|
||||
// Send logs to the game server
|
||||
if (Byond.strictMode) {
|
||||
Byond.sendMessage({
|
||||
type: 'log',
|
||||
fatal: 1,
|
||||
message: stack,
|
||||
});
|
||||
} else if (window.onerror.errorCount <= 1) {
|
||||
stack += '\nWindow is in non-strict mode, future errors are suppressed.';
|
||||
Byond.sendMessage({
|
||||
type: 'log',
|
||||
message: stack,
|
||||
});
|
||||
}
|
||||
// Short-circuit further updates
|
||||
if (Byond.strictMode) {
|
||||
window.update = function () {};
|
||||
window.update.queue = [];
|
||||
}
|
||||
// Prevent default action
|
||||
return true;
|
||||
};
|
||||
|
||||
// Catch unhandled promise rejections
|
||||
window.onunhandledrejection = function (e) {
|
||||
let msg = 'UnhandledRejection';
|
||||
if (e.reason) {
|
||||
msg += ': ' + (e.reason.message || e.reason.description || e.reason);
|
||||
if (e.reason.stack) {
|
||||
e.reason.stack = 'UnhandledRejection: ' + e.reason.stack;
|
||||
}
|
||||
}
|
||||
window.onerror(msg, null, null, null, e.reason);
|
||||
};
|
||||
|
||||
// Helper for augmenting stack traces on fatal errors
|
||||
window.__augmentStack__ = function (stack, error) {
|
||||
return stack + '\nUser Agent: ' + navigator.userAgent;
|
||||
};
|
||||
|
||||
// Incoming message handling
|
||||
// ------------------------------------------------------
|
||||
|
||||
// Message handler
|
||||
window.update = function (rawMessage) {
|
||||
// Push onto the queue (active during initialization)
|
||||
if (window.update.queueActive) {
|
||||
window.update.queue.push(rawMessage);
|
||||
return;
|
||||
}
|
||||
// Parse the message
|
||||
let message = Byond.parseJson(rawMessage);
|
||||
// Notify listeners
|
||||
let listeners = window.update.listeners;
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i](message.type, message.payload);
|
||||
}
|
||||
};
|
||||
|
||||
// Properties and variables of this specific handler
|
||||
window.update.listeners = [];
|
||||
window.update.queue = [];
|
||||
window.update.queueActive = true;
|
||||
window.update.flushQueue = function (listener) {
|
||||
// Disable and clear the queue permanently on short delay
|
||||
if (window.update.queueActive) {
|
||||
window.update.queueActive = false;
|
||||
if (window.setTimeout) {
|
||||
window.setTimeout(() => {
|
||||
window.update.queue = [];
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
// Process queued messages on provided listener
|
||||
let queue = window.update.queue;
|
||||
for (let i = 0; i < queue.length; i++) {
|
||||
let message = Byond.parseJson(queue[i]);
|
||||
listener(message.type, message.payload);
|
||||
}
|
||||
};
|
||||
|
||||
window.replaceHtml = function (inline_html) {
|
||||
let children = document.body.childNodes;
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
if (children[i].nodeValue == ' tgui:inline-html-start ') {
|
||||
while (children[i].nodeValue != ' tgui:inline-html-end ') {
|
||||
children[i].remove();
|
||||
}
|
||||
children[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
document.body.insertAdjacentHTML(
|
||||
'afterbegin',
|
||||
'<!-- tgui:inline-html-start -->' +
|
||||
inline_html +
|
||||
'<!-- tgui:inline-html-end -->'
|
||||
);
|
||||
};
|
||||
112
tgui/packages/tgui-setup/ntos-error.css
Normal file
112
tgui/packages/tgui-setup/ntos-error.css
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Blink polyfill, originally authored on /tg/ by @iamgoofball */
|
||||
blink {
|
||||
animation: 1s linear infinite condemned-blink-effect;
|
||||
}
|
||||
|
||||
@keyframes condemned-blink-effect {
|
||||
0% {
|
||||
visibility: hidden;
|
||||
}
|
||||
50% {
|
||||
visibility: hidden;
|
||||
}
|
||||
100% {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.FatalError {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 12px;
|
||||
font-size: 12px;
|
||||
font-family: Consolas, monospace;
|
||||
color: #ffffff;
|
||||
background-color: #0000dd;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.FatalError--visible {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.FatalError__logo {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
font-size: 10px;
|
||||
line-height: 12px;
|
||||
position: relative;
|
||||
margin: 16px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
animation:
|
||||
FatalError__rainbow 2s linear infinite alternate,
|
||||
FatalError__shadow 4s linear infinite alternate,
|
||||
FatalError__tfmX 3s infinite alternate,
|
||||
FatalError__tfmY 4s infinite alternate;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.FatalError__header {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.FatalError__stack {
|
||||
text-align: left;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.FatalError__footer {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
@keyframes FatalError__rainbow {
|
||||
0% {
|
||||
color: #ff0;
|
||||
}
|
||||
50% {
|
||||
color: #0ff;
|
||||
}
|
||||
100% {
|
||||
color: #f0f;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes FatalError__shadow {
|
||||
0% {
|
||||
left: -2px;
|
||||
text-shadow: 4px 0 #f0f;
|
||||
}
|
||||
50% {
|
||||
left: 0px;
|
||||
text-shadow: 0px 0 #0ff;
|
||||
}
|
||||
100% {
|
||||
left: 2px;
|
||||
text-shadow: -4px 0 #ff0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes FatalError__tfmX {
|
||||
0% {
|
||||
left: 15px;
|
||||
}
|
||||
100% {
|
||||
left: -15px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes FatalError__tfmY {
|
||||
100% {
|
||||
top: -15px;
|
||||
}
|
||||
}
|
||||
14
tgui/packages/tgui-setup/package.json
Normal file
14
tgui/packages/tgui-setup/package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "tgui-setup",
|
||||
"version": "0.0.1",
|
||||
"description": "Minifies assets to inject into tgui.html",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build:helpers": "terser helpers.js -f ascii_only,comments=false -o ../../public/helpers.min.js",
|
||||
"build:style": "cleancss -o ../../public/ntos-error.min.css ntos-error.css"
|
||||
},
|
||||
"dependencies": {
|
||||
"clean-css-cli": "^5.6.3",
|
||||
"terser": "^5.39.0"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import { Button, LabeledList, Section, Slider } from 'tgui-core/components';
|
||||
import {
|
||||
Button,
|
||||
LabeledList,
|
||||
Section,
|
||||
Slider,
|
||||
Stack,
|
||||
} from 'tgui-core/components';
|
||||
|
||||
type Data = {
|
||||
volume_channels: { key; val: number }[];
|
||||
@@ -12,26 +18,34 @@ export const VolumePanel = (props) => {
|
||||
const { volume_channels } = data;
|
||||
|
||||
return (
|
||||
<Window width={350} height={600}>
|
||||
<Window width={550} height={600}>
|
||||
<Window.Content>
|
||||
<Section title="Volume Levels">
|
||||
<Section title="Volume Levels" fill scrollable>
|
||||
<LabeledList>
|
||||
{Object.keys(volume_channels).map((key) => (
|
||||
<LabeledList.Item label={key} key={key}>
|
||||
<Slider
|
||||
width="88%"
|
||||
minValue={0}
|
||||
maxValue={200}
|
||||
value={volume_channels[key] * 100}
|
||||
onChange={(e, val) =>
|
||||
act('adjust_volume', { channel: key, vol: val / 100 })
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
ml={1}
|
||||
icon="undo"
|
||||
onClick={() => act('adjust_volume', { channel: key, vol: 1 })}
|
||||
/>
|
||||
<Stack>
|
||||
<Stack.Item grow>
|
||||
<Slider
|
||||
ml="1rem"
|
||||
minValue={0}
|
||||
maxValue={200}
|
||||
value={volume_channels[key] * 100}
|
||||
onChange={(e, val) =>
|
||||
act('adjust_volume', { channel: key, vol: val / 100 })
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
ml="1rem"
|
||||
icon="undo"
|
||||
onClick={() =>
|
||||
act('adjust_volume', { channel: key, vol: 1 })
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
|
||||
1
tgui/public/helpers.min.js
vendored
Normal file
1
tgui/public/helpers.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
tgui/public/ntos-error.min.css
vendored
Normal file
1
tgui/public/ntos-error.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blink{animation:1s linear infinite condemned-blink-effect}@keyframes condemned-blink-effect{0%{visibility:hidden}50%{visibility:hidden}100%{visibility:visible}}.FatalError{display:none;position:absolute;top:0;left:0;right:0;bottom:0;padding:12px;font-size:12px;font-family:Consolas,monospace;color:#fff;background-color:#00d;z-index:1000;overflow:hidden;text-align:center}.FatalError--visible{display:block!important}.FatalError__logo{display:inline-block;text-align:left;font-size:10px;line-height:12px;position:relative;margin:16px;top:0;left:0;animation:FatalError__rainbow 2s linear infinite alternate,FatalError__shadow 4s linear infinite alternate,FatalError__tfmX 3s infinite alternate,FatalError__tfmY 4s infinite alternate;white-space:pre}.FatalError__header{margin-top:12px}.FatalError__stack{text-align:left;white-space:pre-wrap;word-break:break-all;margin-top:24px;margin-bottom:24px}.FatalError__footer{margin-bottom:24px}@keyframes FatalError__rainbow{0%{color:#ff0}50%{color:#0ff}100%{color:#f0f}}@keyframes FatalError__shadow{0%{left:-2px;text-shadow:4px 0 #f0f}50%{left:0;text-shadow:0 0 #0ff}100%{left:2px;text-shadow:-4px 0 #ff0}}@keyframes FatalError__tfmX{0%{left:15px}100%{left:-15px}}@keyframes FatalError__tfmY{100%{top:-15px}}
|
||||
@@ -1,730 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- Inlined metadata -->
|
||||
<meta id="tgui:windowId" content="[tgui:windowId]">
|
||||
<meta id="tgui:strictMode" content="[tgui:strictMode]">
|
||||
|
||||
<!-- Early setup -->
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
// Utility functions
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
var assign = function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
for (var key in source) {
|
||||
if (hasOwn.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
var parseMetaTag = function (name) {
|
||||
var content = document.getElementById(name).getAttribute('content');
|
||||
if (content === '[' + name + ']') {
|
||||
return null;
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
// BYOND API object
|
||||
// ------------------------------------------------------
|
||||
|
||||
var Byond = window.Byond = {};
|
||||
|
||||
// Expose inlined metadata
|
||||
Byond.windowId = parseMetaTag('tgui:windowId');
|
||||
|
||||
// Backwards compatibility
|
||||
window.__windowId__ = Byond.windowId;
|
||||
|
||||
// Trident engine version
|
||||
Byond.TRIDENT = (function () {
|
||||
var groups = navigator.userAgent.match(/Trident\/(\d+).+?;/i);
|
||||
var majorVersion = groups && groups[1];
|
||||
return majorVersion
|
||||
? parseInt(majorVersion, 10)
|
||||
: null;
|
||||
})();
|
||||
|
||||
// Blink engine version
|
||||
Byond.BLINK = (function () {
|
||||
var groups = navigator.userAgent.match(/Chrome\/(\d+)\./);
|
||||
var majorVersion = groups && groups[1];
|
||||
return majorVersion ? parseInt(majorVersion, 10) : null;
|
||||
})();
|
||||
|
||||
// Basic checks to detect whether this page runs in BYOND
|
||||
var isByond = (Byond.TRIDENT !== null || Byond.BLINK !== null || window.cef_to_byond)
|
||||
&& location.hostname === '127.0.0.1'
|
||||
&& location.search !== '?external';
|
||||
//As of BYOND 515 the path doesn't seem to include tmp dir anymore if you're trying to open tgui in external browser and looking why it doesn't work
|
||||
//&& location.pathname.indexOf('/tmp') === 0
|
||||
|
||||
// Version constants
|
||||
Byond.IS_BYOND = isByond;
|
||||
|
||||
// Strict mode flag
|
||||
Byond.strictMode = Boolean(Number(parseMetaTag('tgui:strictMode')));
|
||||
|
||||
// Callbacks for asynchronous calls
|
||||
Byond.__callbacks__ = [];
|
||||
|
||||
// Reviver for BYOND JSON
|
||||
var byondJsonReviver = function (key, value) {
|
||||
if (typeof value === 'object' && value !== null && value.__number__) {
|
||||
return parseFloat(value.__number__);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
// Makes a BYOND call.
|
||||
// See: https://secure.byond.com/docs/ref/skinparams.html
|
||||
Byond.call = function (path, params) {
|
||||
// Not running in BYOND, abort.
|
||||
if (!isByond) {
|
||||
return;
|
||||
}
|
||||
// Build the URL
|
||||
var url = (path || '') + '?';
|
||||
var i = 0;
|
||||
if (params) {
|
||||
for (var key in params) {
|
||||
if (hasOwn.call(params, key)) {
|
||||
if (i++ > 0) {
|
||||
url += '&';
|
||||
}
|
||||
var value = params[key];
|
||||
if (value === null || value === undefined) {
|
||||
value = '';
|
||||
}
|
||||
url += encodeURIComponent(key)
|
||||
+ '=' + encodeURIComponent(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're a Chromium client, just use the fancy method
|
||||
if (window.cef_to_byond) {
|
||||
cef_to_byond('byond://' + url);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform a standard call via location.href
|
||||
if (url.length < 2048) {
|
||||
location.href = 'byond://' + url;
|
||||
return;
|
||||
}
|
||||
// Send an HTTP request to DreamSeeker's HTTP server.
|
||||
// Allows sending much bigger payloads.
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
Byond.callAsync = function (path, params) {
|
||||
if (!window.Promise) {
|
||||
throw new Error('Async calls require API level of ES2015 or later.');
|
||||
}
|
||||
var index = Byond.__callbacks__.length;
|
||||
var promise = new window.Promise(function (resolve) {
|
||||
Byond.__callbacks__.push(resolve);
|
||||
});
|
||||
Byond.call(path, assign({}, params, {
|
||||
callback: 'Byond.__callbacks__[' + index + ']',
|
||||
}));
|
||||
return promise;
|
||||
};
|
||||
|
||||
Byond.topic = function (params) {
|
||||
return Byond.call('', params);
|
||||
};
|
||||
|
||||
Byond.command = function (command) {
|
||||
return Byond.call('winset', {
|
||||
command: command,
|
||||
});
|
||||
};
|
||||
|
||||
Byond.winget = function (id, propName) {
|
||||
if (id === null) {
|
||||
id = '';
|
||||
}
|
||||
var isArray = propName instanceof Array;
|
||||
var isSpecific = propName && propName !== '*' && !isArray;
|
||||
var promise = Byond.callAsync('winget', {
|
||||
id: id,
|
||||
property: isArray && propName.join(',') || propName || '*',
|
||||
});
|
||||
if (isSpecific) {
|
||||
promise = promise.then(function (props) {
|
||||
return props[propName];
|
||||
});
|
||||
}
|
||||
return promise;
|
||||
};
|
||||
|
||||
Byond.winset = function (id, propName, propValue) {
|
||||
if (id === null) {
|
||||
id = '';
|
||||
}
|
||||
else if (typeof id === 'object') {
|
||||
return Byond.call('winset', id);
|
||||
}
|
||||
var props = {};
|
||||
if (typeof propName === 'string') {
|
||||
props[propName] = propValue;
|
||||
}
|
||||
else {
|
||||
assign(props, propName);
|
||||
}
|
||||
props.id = id;
|
||||
return Byond.call('winset', props);
|
||||
};
|
||||
|
||||
Byond.parseJson = function (json) {
|
||||
try {
|
||||
return JSON.parse(json, byondJsonReviver);
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error('JSON parsing error: ' + (err && err.message));
|
||||
}
|
||||
};
|
||||
|
||||
Byond.sendMessage = function (type, payload) {
|
||||
var message = typeof type === 'string'
|
||||
? { type: type, payload: payload }
|
||||
: type;
|
||||
// JSON-encode the payload
|
||||
if (message.payload !== null && message.payload !== undefined) {
|
||||
message.payload = JSON.stringify(message.payload);
|
||||
|
||||
if(!Byond.TRIDENT && message.payload.length > 1024) {
|
||||
var chunks = [];
|
||||
|
||||
for(var i = 0, charsLength = message.payload.length; i < charsLength; i += 1024) {
|
||||
chunks.push(message.payload.substring(i, i + 1024))
|
||||
}
|
||||
|
||||
for(var i = 0; i < chunks.length; i++) {
|
||||
var to_send = chunks[i]
|
||||
|
||||
message = { type: type, packet: to_send, packetId: i + 1, totalPackets: chunks.length, tgui: 1, window_id: Byond.windowId };
|
||||
Byond.topic(message);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Append an identifying header
|
||||
assign(message, {
|
||||
tgui: 1,
|
||||
window_id: Byond.windowId,
|
||||
});
|
||||
Byond.topic(message);
|
||||
};
|
||||
|
||||
// This function exists purely for debugging, do not use it in code!
|
||||
Byond.injectMessage = function (type, payload) {
|
||||
window.update(JSON.stringify({ type: type, payload: payload }));
|
||||
};
|
||||
|
||||
Byond.subscribe = function (listener) {
|
||||
window.update.flushQueue(listener);
|
||||
window.update.listeners.push(listener);
|
||||
};
|
||||
|
||||
Byond.subscribeTo = function (type, listener) {
|
||||
var _listener = function (_type, payload) {
|
||||
if (_type === type) {
|
||||
listener(payload);
|
||||
}
|
||||
};
|
||||
window.update.flushQueue(_listener);
|
||||
window.update.listeners.push(_listener);
|
||||
};
|
||||
|
||||
// Asset loaders
|
||||
// ------------------------------------------------------
|
||||
|
||||
var RETRY_ATTEMPTS = 5;
|
||||
var RETRY_WAIT_INITIAL = 500;
|
||||
var RETRY_WAIT_INCREMENT = 500;
|
||||
|
||||
var loadedAssetByUrl = {};
|
||||
|
||||
var isStyleSheetLoaded = function (node, url) {
|
||||
var styleSheet = node.sheet;
|
||||
if (styleSheet) {
|
||||
return styleSheet.rules.length > 0;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var injectNode = function (node) {
|
||||
if (!document.body) {
|
||||
setTimeout(function () {
|
||||
injectNode(node);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var refs = document.body.childNodes;
|
||||
var ref = refs[refs.length - 1];
|
||||
ref.parentNode.insertBefore(node, ref.nextSibling);
|
||||
};
|
||||
|
||||
var loadAsset = function (options) {
|
||||
var url = options.url;
|
||||
var type = options.type;
|
||||
var sync = options.sync;
|
||||
var attempt = options.attempt || 0;
|
||||
if (loadedAssetByUrl[url]) {
|
||||
return;
|
||||
}
|
||||
loadedAssetByUrl[url] = options;
|
||||
// Generic retry function
|
||||
var retry = function () {
|
||||
if (attempt >= RETRY_ATTEMPTS) {
|
||||
var errorMessage = "Error: Failed to load the asset "
|
||||
+ "'" + url + "' after several attempts.";
|
||||
if (type === 'css') {
|
||||
errorMessage += + "\nStylesheet was either not found, "
|
||||
+ "or you're trying to load an empty stylesheet "
|
||||
+ "that has no CSS rules in it.";
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
setTimeout(function () {
|
||||
loadedAssetByUrl[url] = null;
|
||||
options.attempt += 1;
|
||||
loadAsset(options);
|
||||
}, RETRY_WAIT_INITIAL + attempt * RETRY_WAIT_INCREMENT);
|
||||
};
|
||||
// JS specific code
|
||||
if (type === 'js') {
|
||||
var node = document.createElement('script');
|
||||
node.type = 'text/javascript';
|
||||
node.crossOrigin = 'anonymous';
|
||||
node.src = url;
|
||||
if (sync) {
|
||||
node.defer = true;
|
||||
}
|
||||
else {
|
||||
node.async = true;
|
||||
}
|
||||
node.onerror = function () {
|
||||
node.onerror = null;
|
||||
node.parentNode.removeChild(node);
|
||||
node = null;
|
||||
retry();
|
||||
};
|
||||
injectNode(node);
|
||||
return;
|
||||
}
|
||||
// CSS specific code
|
||||
if (type === 'css') {
|
||||
var node = document.createElement('link');
|
||||
node.type = 'text/css';
|
||||
node.rel = 'stylesheet';
|
||||
node.crossOrigin = 'anonymous';
|
||||
node.href = url;
|
||||
// Temporarily set media to something inapplicable
|
||||
// to ensure it'll fetch without blocking render
|
||||
if (!sync) {
|
||||
node.media = 'only x';
|
||||
}
|
||||
var removeNodeAndRetry = function () {
|
||||
node.parentNode.removeChild(node);
|
||||
node = null;
|
||||
retry();
|
||||
}
|
||||
// 516: Chromium won't call onload() if there is a 404 error
|
||||
// Legacy IE doesn't use onerror, so we retain that
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#stylesheet_load_events
|
||||
node.onerror = function () {
|
||||
node.onerror = null;
|
||||
removeNodeAndRetry();
|
||||
}
|
||||
node.onload = function () {
|
||||
node.onload = null;
|
||||
if (isStyleSheetLoaded(node, url)) {
|
||||
// Render the stylesheet
|
||||
node.media = 'all';
|
||||
return;
|
||||
}
|
||||
// Try again
|
||||
removeNodeAndRetry();
|
||||
};
|
||||
injectNode(node);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Byond.loadJs = function (url, sync) {
|
||||
loadAsset({ url: url, sync: sync, type: 'js' });
|
||||
};
|
||||
|
||||
Byond.loadCss = function (url, sync) {
|
||||
loadAsset({ url: url, sync: sync, type: 'css' });
|
||||
};
|
||||
|
||||
Byond.saveBlob = function (blob, filename, ext) {
|
||||
if (window.navigator.msSaveBlob) {
|
||||
window.navigator.msSaveBlob(blob, filename)
|
||||
} else if (window.showSaveFilePicker) {
|
||||
var accept = {};
|
||||
accept[blob.type] = [ext];
|
||||
|
||||
var opts = {
|
||||
suggestedName: filename,
|
||||
types: [
|
||||
{
|
||||
description: "SS13 file",
|
||||
accept: accept,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
try {
|
||||
window.showSaveFilePicker(opts).then(function (fileHandle) {
|
||||
fileHandle.createWritable().then(function (writeableFileHandle) {
|
||||
writeableFileHandle.write(blob).then(function () {
|
||||
writeableFileHandle.close()
|
||||
}).catch(function (e) { console.error(e) });
|
||||
}).catch(function (e) { console.error(e) });
|
||||
}).catch(function (e) { console.error(e) });
|
||||
} catch (e) { console.error(e) }
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Icon cache
|
||||
Byond.iconRefMap = {};
|
||||
})();
|
||||
|
||||
// Error handling
|
||||
// ------------------------------------------------------
|
||||
|
||||
window.onerror = function (msg, url, line, col, error) {
|
||||
window.onerror.errorCount = (window.onerror.errorCount || 0) + 1;
|
||||
// Proper stacktrace
|
||||
var stack = error && error.stack;
|
||||
// Ghetto stacktrace
|
||||
if (!stack) {
|
||||
stack = msg + '\n at ' + url + ':' + line;
|
||||
if (col) {
|
||||
stack += ':' + col;
|
||||
}
|
||||
}
|
||||
// Augment the stack
|
||||
stack = window.__augmentStack__(stack, error);
|
||||
// Print error to the page
|
||||
if (Byond.strictMode) {
|
||||
var errorRoot = document.getElementById('FatalError');
|
||||
var errorStack = document.getElementById('FatalError__stack');
|
||||
if (errorRoot) {
|
||||
errorRoot.className = 'FatalError FatalError--visible';
|
||||
if (window.onerror.__stack__) {
|
||||
window.onerror.__stack__ += '\n\n' + stack;
|
||||
}
|
||||
else {
|
||||
window.onerror.__stack__ = stack;
|
||||
}
|
||||
var textProp = 'textContent';
|
||||
errorStack[textProp] = window.onerror.__stack__;
|
||||
}
|
||||
// Set window geometry
|
||||
var setFatalErrorGeometry = function () {
|
||||
Byond.winset(Byond.windowId, {
|
||||
titlebar: true,
|
||||
'is-visible': true,
|
||||
'can-resize': true,
|
||||
});
|
||||
};
|
||||
setFatalErrorGeometry();
|
||||
setInterval(setFatalErrorGeometry, 1000);
|
||||
}
|
||||
// Send logs to the game server
|
||||
if (Byond.strictMode) {
|
||||
Byond.sendMessage({
|
||||
type: 'log',
|
||||
fatal: 1,
|
||||
message: stack,
|
||||
});
|
||||
}
|
||||
else if (window.onerror.errorCount <= 1) {
|
||||
stack += '\nWindow is in non-strict mode, future errors are suppressed.';
|
||||
Byond.sendMessage({
|
||||
type: 'log',
|
||||
message: stack,
|
||||
});
|
||||
}
|
||||
// Short-circuit further updates
|
||||
if (Byond.strictMode) {
|
||||
window.update = function () { };
|
||||
window.update.queue = [];
|
||||
}
|
||||
// Prevent default action
|
||||
return true;
|
||||
};
|
||||
|
||||
// Catch unhandled promise rejections
|
||||
window.onunhandledrejection = function (e) {
|
||||
var msg = 'UnhandledRejection';
|
||||
if (e.reason) {
|
||||
msg += ': ' + (e.reason.message || e.reason.description || e.reason);
|
||||
if (e.reason.stack) {
|
||||
e.reason.stack = 'UnhandledRejection: ' + e.reason.stack;
|
||||
}
|
||||
}
|
||||
window.onerror(msg, null, null, null, e.reason);
|
||||
};
|
||||
|
||||
// Helper for augmenting stack traces on fatal errors
|
||||
window.__augmentStack__ = function (stack, error) {
|
||||
return stack + '\nUser Agent: ' + navigator.userAgent;
|
||||
};
|
||||
|
||||
// Incoming message handling
|
||||
// ------------------------------------------------------
|
||||
|
||||
// Message handler
|
||||
window.update = function (rawMessage) {
|
||||
// Push onto the queue (active during initialization)
|
||||
if (window.update.queueActive) {
|
||||
window.update.queue.push(rawMessage);
|
||||
return;
|
||||
}
|
||||
// Parse the message
|
||||
var message = Byond.parseJson(rawMessage);
|
||||
// Notify listeners
|
||||
var listeners = window.update.listeners;
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
listeners[i](message.type, message.payload);
|
||||
}
|
||||
};
|
||||
|
||||
// Properties and variables of this specific handler
|
||||
window.update.listeners = [];
|
||||
window.update.queue = [];
|
||||
window.update.queueActive = true;
|
||||
window.update.flushQueue = function (listener) {
|
||||
// Disable and clear the queue permanently on short delay
|
||||
if (window.update.queueActive) {
|
||||
window.update.queueActive = false;
|
||||
if (window.setTimeout) {
|
||||
window.setTimeout(function () {
|
||||
window.update.queue = [];
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
// Process queued messages on provided listener
|
||||
var queue = window.update.queue;
|
||||
for (var i = 0; i < queue.length; i++) {
|
||||
var message = Byond.parseJson(queue[i]);
|
||||
listener(message.type, message.payload);
|
||||
}
|
||||
};
|
||||
|
||||
window.replaceHtml = function (inline_html) {
|
||||
var children = document.body.childNodes;
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].nodeValue == " tgui:inline-html-start ") {
|
||||
while (children[i].nodeValue != " tgui:inline-html-end ") {
|
||||
children[i].remove();
|
||||
}
|
||||
children[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
document.body.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<!-- tgui:inline-html-start -->"
|
||||
+ inline_html
|
||||
+ "<!-- tgui:inline-html-end -->"
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Blink polyfill, originally authored on /tg/ by @iamgoofball */
|
||||
blink {
|
||||
animation: 1s linear infinite condemned-blink-effect;
|
||||
}
|
||||
|
||||
@keyframes condemned-blink-effect {
|
||||
0% {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
50% {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
100% {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.FatalError {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 12px;
|
||||
font-size: 12px;
|
||||
font-family: Consolas, monospace;
|
||||
color: #ffffff;
|
||||
background-color: #0000dd;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.FatalError--visible {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.FatalError__logo {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
font-size: 10px;
|
||||
line-height: 12px;
|
||||
position: relative;
|
||||
margin: 16px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
animation:
|
||||
FatalError__rainbow 2s linear infinite alternate,
|
||||
FatalError__shadow 4s linear infinite alternate,
|
||||
FatalError__tfmX 3s infinite alternate,
|
||||
FatalError__tfmY 4s infinite alternate;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.FatalError__header {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.FatalError__stack {
|
||||
text-align: left;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.FatalError__footer {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
@keyframes FatalError__rainbow {
|
||||
0% {
|
||||
color: #ff0;
|
||||
}
|
||||
|
||||
50% {
|
||||
color: #0ff;
|
||||
}
|
||||
|
||||
100% {
|
||||
color: #f0f;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes FatalError__shadow {
|
||||
0% {
|
||||
left: -2px;
|
||||
text-shadow: 4px 0 #f0f;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: 0px;
|
||||
text-shadow: 0px 0 #0ff;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 2px;
|
||||
text-shadow: -4px 0 #ff0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes FatalError__tfmX {
|
||||
0% {
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: -15px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes FatalError__tfmY {
|
||||
100% {
|
||||
top: -15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- tgui:inline-css -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- tgui:assets -->
|
||||
<!-- tgui:inline-html-start -->
|
||||
<!-- tgui:inline-html -->
|
||||
<!-- tgui:inline-html-end -->
|
||||
<!-- tgui:inline-js -->
|
||||
|
||||
<!-- Root element for tgui interfaces -->
|
||||
<div id="react-root"></div>
|
||||
|
||||
<!-- Fatal error container -->
|
||||
<div id="FatalError" class="FatalError">
|
||||
<div class="FatalError__logo">
|
||||
ooooo ooo . .oooooo. .oooooo..o
|
||||
`888b. `8' .o8 d8P' `Y8b d8P' `Y8
|
||||
8 `88b. 8 .o888oo 888 888 Y88bo.
|
||||
8 `88b. 8 888 888 888 `"Y8888o.
|
||||
8 `88b.8 888 888 888 `"Y88b
|
||||
8 `888 888 . `88b d88' oo .d8P
|
||||
o8o `8 "888" `Y8bood8P' 8""88888P'
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- Inlined metadata -->
|
||||
<meta id="tgui:windowId" content="[tgui:windowId]" />
|
||||
<meta id="tgui:strictMode" content="[tgui:strictMode]" />
|
||||
|
||||
<!-- Early setup -->
|
||||
<!-- tgui:helpers -->
|
||||
<!-- tgui:ntos-error -->
|
||||
<!-- tgui:inline-css -->
|
||||
</head>
|
||||
<body>
|
||||
<!-- tgui:assets -->
|
||||
<!-- tgui:inline-html-start -->
|
||||
<!-- tgui:inline-html -->
|
||||
<!-- tgui:inline-html-end -->
|
||||
<!-- tgui:inline-js -->
|
||||
|
||||
<!-- Root element for tgui interfaces -->
|
||||
<div id="react-root"></div>
|
||||
|
||||
<!-- Fatal error container -->
|
||||
<div id="FatalError" class="FatalError">
|
||||
<!-- prettier-ignore -->
|
||||
<div class="FatalError__logo">
|
||||
ooooo ooo . .oooooo. .oooooo..o
|
||||
`888b. `8' .o8 d8P' `Y8b d8P' `Y8
|
||||
8 `88b. 8 .o888oo 888 888 Y88bo.
|
||||
8 `88b. 8 888 888 888 `"Y8888o.
|
||||
8 `88b.8 888 888 888 `"Y88b
|
||||
8 `888 888 . `88b d88' oo .d8P
|
||||
o8o `8 "888" `Y8bood8P' 8""88888P'
|
||||
</div>
|
||||
<marquee class="FatalError__header">
|
||||
A fatal exception has occurred at 002B:C562F1B7 in TGUI. The current
|
||||
application will be terminated. Send the copy of the following stack
|
||||
trace to an authorized Nanotrasen incident handler at
|
||||
https://github.com/VOREStation/VOREStation. Thank you for your
|
||||
cooperation.
|
||||
</marquee>
|
||||
<div id="FatalError__stack" class="FatalError__stack"></div>
|
||||
<div class="FatalError__footer">
|
||||
<!-- tgui:nt-copyright -->
|
||||
</div>
|
||||
</div>
|
||||
<marquee class="FatalError__header">
|
||||
A fatal exception has occurred at 002B:C562F1B7 in TGUI.
|
||||
The current application will be terminated.
|
||||
Send the copy of the following stack trace to an authorized
|
||||
Nanotrasen incident handler at https://github.com/VOREStation/VOREStation.
|
||||
Thank you for your cooperation.
|
||||
</marquee>
|
||||
<div id="FatalError__stack" class="FatalError__stack"></div>
|
||||
<div class="FatalError__footer">
|
||||
<!-- tgui:nt-copyright -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<div class="NoticeBox">
|
||||
<div>Javascript is required in order to use this interface.</div>
|
||||
<div>Please enable Javascript and restart the game.</div>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<script>
|
||||
// Signal tgui that we're ready to receive updates
|
||||
Byond.sendMessage('ready');
|
||||
</script>
|
||||
</body>
|
||||
<noscript>
|
||||
<div class="NoticeBox">
|
||||
<div>Javascript is required in order to use this interface.</div>
|
||||
<div>Please enable Javascript and restart the game.</div>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<script>
|
||||
// Signal tgui that we're ready to receive updates
|
||||
Byond.sendMessage('ready');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -6210,7 +6210,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"chokidar@npm:^3.4.1":
|
||||
"chokidar@npm:^3.4.1, chokidar@npm:^3.5.2":
|
||||
version: 3.6.0
|
||||
resolution: "chokidar@npm:3.6.0"
|
||||
dependencies:
|
||||
@@ -6316,6 +6316,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-css-cli@npm:^5.6.3":
|
||||
version: 5.6.3
|
||||
resolution: "clean-css-cli@npm:5.6.3"
|
||||
dependencies:
|
||||
chokidar: "npm:^3.5.2"
|
||||
clean-css: "npm:^5.3.3"
|
||||
commander: "npm:7.x"
|
||||
glob: "npm:^7.1.6"
|
||||
bin:
|
||||
cleancss: bin/cleancss
|
||||
checksum: 10c0/678562c4b3ba4bd150cee0fd838b0cb9b645e3260dd5ff8b9e1456215e86bb6389e3a7f542194c125eaf700034e60ab14570837d7e36663bd5a283904f86f656
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-css@npm:^4.2.3":
|
||||
version: 4.2.4
|
||||
resolution: "clean-css@npm:4.2.4"
|
||||
@@ -6325,6 +6339,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-css@npm:^5.3.3":
|
||||
version: 5.3.3
|
||||
resolution: "clean-css@npm:5.3.3"
|
||||
dependencies:
|
||||
source-map: "npm:~0.6.0"
|
||||
checksum: 10c0/381de7523e23f3762eb180e327dcc0cedafaf8cb1cd8c26b7cc1fc56e0829a92e734729c4f955394d65ed72fb62f82d8baf78af34b33b8a7d41ebad2accdd6fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clean-stack@npm:^2.0.0":
|
||||
version: 2.2.0
|
||||
resolution: "clean-stack@npm:2.2.0"
|
||||
@@ -6501,6 +6524,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"commander@npm:7.x, commander@npm:^7.2.0":
|
||||
version: 7.2.0
|
||||
resolution: "commander@npm:7.2.0"
|
||||
checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"commander@npm:^10.0.1":
|
||||
version: 10.0.1
|
||||
resolution: "commander@npm:10.0.1"
|
||||
@@ -6522,13 +6552,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"commander@npm:^7.2.0":
|
||||
version: 7.2.0
|
||||
resolution: "commander@npm:7.2.0"
|
||||
checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"common-tags@npm:^1.8.0":
|
||||
version: 1.8.2
|
||||
resolution: "common-tags@npm:1.8.2"
|
||||
@@ -19060,7 +19083,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser@npm:^5.3.4, terser@npm:^5.31.1":
|
||||
"terser@npm:^5.3.4, terser@npm:^5.31.1, terser@npm:^5.39.0":
|
||||
version: 5.39.0
|
||||
resolution: "terser@npm:5.39.0"
|
||||
dependencies:
|
||||
@@ -19171,6 +19194,15 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"tgui-setup@workspace:packages/tgui-setup":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "tgui-setup@workspace:packages/tgui-setup"
|
||||
dependencies:
|
||||
clean-css-cli: "npm:^5.6.3"
|
||||
terser: "npm:^5.39.0"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"tgui-workspace@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "tgui-workspace@workspace:."
|
||||
|
||||
Reference in New Issue
Block a user