Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some more basic 516 prep #4268

Merged
merged 12 commits into from
Dec 2, 2024
2 changes: 1 addition & 1 deletion code/_onclick/hud/hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
for(var/group_key as anything in master_groups)
var/datum/plane_master_group/group = master_groups[group_key]
group.relay_loc = new_relay_loc
group.rebuild_plane_masters()
group.rebuild_hud()
client.rebuild_plane_masters = FALSE
RegisterSignal(client, COMSIG_CLIENT_SET_EYE, PROC_REF(on_eye_change))
on_eye_change(null, null, client.eye)
Expand Down
12 changes: 11 additions & 1 deletion code/modules/admin/admin.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
if(!check_rights(0))
return

var/dat = "<center><B>Game Panel</B></center><hr>"
var/dat = "<html><meta charset='UTF-8'><head><title>Game Panel</title></head><body>"
dat += "<center><B>Game Panel</B></center><hr>"
if(SSticker.current_state <= GAME_STATE_PREGAME)
dat += "<A href='byond://?src=[REF(src)];[HrefToken()];f_dynamic_roundstart=1'>(Force Roundstart Rulesets)</A><br>"
if (GLOB.dynamic_forced_roundstart_ruleset.len > 0)
Expand All @@ -51,6 +52,7 @@
if(marked_datum && istype(marked_datum, /atom))
dat += "<A href='byond://?src=[REF(src)];[HrefToken()];dupe_marked_datum=1'>Duplicate Marked Datum</A><br>"

dat += "</body></html>"
usr << browse(dat, "window=admin2;size=240x280")
return

Expand Down Expand Up @@ -132,6 +134,12 @@

/datum/admins/proc/dynamic_mode_options(mob/user)
var/dat = {"
<html>
<meta charset='UTF-8'>
<head>
<title>Game Panel</title>
</head>
<body>
<center><B><h2>Dynamic Mode Options</h2></B></center><hr>
<br/>
<h3>Common options</h3>
Expand All @@ -149,6 +157,8 @@
<br/>
<b>Stacking threeshold:</b> Current value : <a href='byond://?src=[REF(src)];[HrefToken()];f_dynamic_stacking_limit=1'><b>[GLOB.dynamic_stacking_limit]</b></a>.
<br/>The threshold at which "round-ender" rulesets will stack. A value higher than 100 ensure this never happens. <br/>
</body>
</html>
"}

user << browse(dat, "window=dyn_mode_options;size=900x650")
Expand Down
6 changes: 6 additions & 0 deletions code/modules/admin/holder2.dm
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ GLOBAL_PROTECT(href_token)
owner.mentor_datum_set()

try_give_profiling()
try_give_devtools()

/datum/admins/proc/disassociate()
if(IsAdminAdvancedProcCall())
Expand Down Expand Up @@ -403,6 +404,11 @@ GLOBAL_PROTECT(href_token)

return combined_flags

/datum/admins/proc/try_give_devtools()
if(!(rank_flags() & R_DEBUG) || owner.byond_version < 516)
return
winset(owner, null, "browser-options=byondstorage,find,devtools")

/datum/admins/proc/try_give_profiling()
if (CONFIG_GET(flag/forbid_admin_profiling))
return
Expand Down
64 changes: 34 additions & 30 deletions code/modules/client/client_procs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -51,37 +51,38 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
return

// Rate limiting
var/mtl = CONFIG_GET(number/minute_topic_limit)
if (!holder && mtl)
var/minute = round(world.time, 600)
if (!topiclimiter)
topiclimiter = new(LIMITER_SIZE)
if (minute != topiclimiter[CURRENT_MINUTE])
topiclimiter[CURRENT_MINUTE] = minute
topiclimiter[MINUTE_COUNT] = 0
topiclimiter[MINUTE_COUNT] += 1
if (topiclimiter[MINUTE_COUNT] > mtl)
var/msg = "Your previous action was ignored because you've done too many in a minute."
if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
topiclimiter[ADMINSWARNED_AT] = minute
msg += " Administrators have been informed."
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
to_chat(src, span_danger("[msg]"))
return
if(!holder && href_list["window_id"] != "statbrowser")
var/mtl = CONFIG_GET(number/minute_topic_limit)
if (mtl)
var/minute = round(world.time, 1 MINUTES)
if (!topiclimiter)
topiclimiter = new(LIMITER_SIZE)
if (minute != topiclimiter[CURRENT_MINUTE])
topiclimiter[CURRENT_MINUTE] = minute
topiclimiter[MINUTE_COUNT] = 0
topiclimiter[MINUTE_COUNT] += 1
if (topiclimiter[MINUTE_COUNT] > mtl)
var/msg = "Your previous action was ignored because you've done too many in a minute."
if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
topiclimiter[ADMINSWARNED_AT] = minute
msg += " Administrators have been informed."
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
to_chat(src, span_danger("[msg]"))
return

var/stl = CONFIG_GET(number/second_topic_limit)
if (!holder && stl && href_list["window_id"] != "statbrowser")
var/second = round(world.time, 10)
if (!topiclimiter)
topiclimiter = new(LIMITER_SIZE)
if (second != topiclimiter[CURRENT_SECOND])
topiclimiter[CURRENT_SECOND] = second
topiclimiter[SECOND_COUNT] = 0
topiclimiter[SECOND_COUNT] += 1
if (topiclimiter[SECOND_COUNT] > stl)
to_chat(src, span_danger("Your previous action was ignored because you've done too many in a second"))
return
var/stl = CONFIG_GET(number/second_topic_limit)
if (stl)
var/second = round(world.time, 1 SECONDS)
if (!topiclimiter)
topiclimiter = new(LIMITER_SIZE)
if (second != topiclimiter[CURRENT_SECOND])
topiclimiter[CURRENT_SECOND] = second
topiclimiter[SECOND_COUNT] = 0
topiclimiter[SECOND_COUNT] += 1
if (topiclimiter[SECOND_COUNT] > stl)
to_chat(src, span_danger("Your previous action was ignored because you've done too many in a second"))
return

// Tgui Topic middleware
if(tgui_Topic(href_list))
Expand Down Expand Up @@ -224,6 +225,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
///////////

/client/New(TopicData)
if(byond_version >= 516) // Enable 516 compat browser storage mechanisms
winset(src, "", "browser-options=byondstorage,find")

var/tdata = TopicData //save this for later use
TopicData = null //Prevent calls to client.Topic from connect

Expand Down
2 changes: 1 addition & 1 deletion code/modules/photography/photos/photo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
user << browse_rsc(picture.picture_image, "tmp_photo.png")
user << browse("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>[name]</title></head>" \
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
+ "<img src='tmp_photo.png' width='480' style='-ms-interpolation-mode:nearest-neighbor' />" \
+ "<img src='tmp_photo.png' width='480' style='-ms-interpolation-mode:nearest-neighbor; image-rendering:pixelated' />" \
+ "[scribble ? "<br>Written on the back:<br><i>[scribble]</i>" : ""]"\
+ "</body></html>", "window=photo_showing;size=480x608")
onclose(user, "[name]")
Expand Down
5 changes: 5 additions & 0 deletions code/modules/tgui_panel/external.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@
// 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")
if(byond_version >= 516)
var/list/options = list("byondstorage", "find")
if(check_rights_for(src, R_DEBUG))
options += "devtools"
winset(src, null, "browser-options=[options.Join(",")]")

/client/verb/refresh_tgui()
set name = "Refresh TGUI"
Expand Down
3 changes: 2 additions & 1 deletion html/browser/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ body
hr
{
background-color: #40628a;
height: 1px;
height: 2px;
border: 0;
}

a, button, a:link, a:visited, a:active, .linkOn, .linkOff
Expand Down
10 changes: 10 additions & 0 deletions html/statbrowser.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.light:root {
--scrollbar-base: #f2f2f2;
--scrollbar-thumb: #a7a7a7;
}

body {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 12px !important;
Expand All @@ -7,6 +12,11 @@ body {
overflow-y: scroll;
}

.dark:root {
--scrollbar-base: #181818;
--scrollbar-thumb: #363636;
}

body.dark {
background-color: #131313;
color: #b2c4dd;
Expand Down
55 changes: 25 additions & 30 deletions tgui/packages/common/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

export const IMPL_MEMORY = 0;
export const IMPL_LOCAL_STORAGE = 1;
export const IMPL_HUB_STORAGE = 1;
export const IMPL_INDEXED_DB = 2;

const INDEXED_DB_VERSION = 1;
Expand All @@ -25,14 +25,11 @@ const testGeneric = (testFn) => () => {
}
};

// Localstorage can sometimes throw an error, even if DOM storage is not
// disabled in IE11 settings.
// See: https://superuser.com/questions/1080011
// prettier-ignore
const testLocalStorage = testGeneric(() => (
window.localStorage && window.localStorage.getItem
));
const testHubStorage = testGeneric(
() => window.hubStorage && window.hubStorage.getItem,
);

// TODO: Remove with 516
// prettier-ignore
const testIndexedDb = testGeneric(() => (
(window.indexedDB || window.msIndexedDB)
Expand All @@ -45,49 +42,50 @@ class MemoryBackend {
this.store = {};
}

get(key) {
async get(key) {
return this.store[key];
}

set(key, value) {
async set(key, value) {
this.store[key] = value;
}

remove(key) {
async remove(key) {
this.store[key] = undefined;
}

clear() {
async clear() {
this.store = {};
}
}

class LocalStorageBackend {
class HubStorageBackend {
constructor() {
this.impl = IMPL_LOCAL_STORAGE;
this.impl = IMPL_HUB_STORAGE;
}

get(key) {
const value = localStorage.getItem(key);
async get(key) {
const value = await window.hubStorage.getItem(key);
if (typeof value === 'string') {
return JSON.parse(value);
}
}

set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
window.hubStorage.setItem(key, JSON.stringify(value));
}

remove(key) {
localStorage.removeItem(key);
window.hubStorage.removeItem(key);
}

clear() {
localStorage.clear();
window.hubStorage.clear();
}
}

class IndexedDbBackend {
// TODO: Remove with 516
constructor() {
this.impl = IMPL_INDEXED_DB;
/** @type {Promise<IDBDatabase>} */
Expand All @@ -108,7 +106,7 @@ class IndexedDbBackend {
});
}

getStore(mode) {
async getStore(mode) {
// prettier-ignore
return this.dbPromise.then((db) => db
.transaction(INDEXED_DB_STORE_NAME, mode)
Expand All @@ -125,13 +123,6 @@ class IndexedDbBackend {
}

async set(key, value) {
// The reason we don't _save_ null is because IE 10 does
// not support saving the `null` type in IndexedDB. How
// ironic, given the bug below!
// See: https://github.com/mozilla/localForage/issues/161
if (value === null) {
value = undefined;
}
// NOTE: We deliberately make this operation transactionless
const store = await this.getStore(READ_WRITE);
store.put(value, key);
Expand All @@ -157,16 +148,20 @@ class IndexedDbBackend {
class StorageProxy {
constructor() {
this.backendPromise = (async () => {
if (!Byond.TRIDENT && testHubStorage()) {
return new HubStorageBackend();
}
// TODO: Remove with 516
if (testIndexedDb()) {
try {
const backend = new IndexedDbBackend();
await backend.dbPromise;
return backend;
} catch {}
}
if (testLocalStorage()) {
return new LocalStorageBackend();
}
console.warn(
'No supported storage backend found. Using in-memory storage.',
);
return new MemoryBackend();
})();
}
Expand Down
6 changes: 3 additions & 3 deletions tgui/packages/tgui-panel/chat/renderer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const createReconnectedNode = () => {
const handleImageError = (e) => {
setTimeout(() => {
/** @type {HTMLImageElement} */
const node = e.target;
const node = Byond.BLINK !== null ? e : e.target;
const attempts = parseInt(node.getAttribute('data-reload-n'), 10) || 0;
if (attempts >= IMAGE_RETRY_LIMIT) {
logger.error(`failed to load an image after ${attempts} attempts`);
Expand Down Expand Up @@ -163,7 +163,7 @@ class ChatRenderer {
// Find scrollable parent
this.scrollNode = findNearestScrollableParent(this.rootNode);
this.scrollNode.addEventListener('scroll', this.handleScroll);
setImmediate(() => {
setTimeout(() => {
this.scrollToBottom();
});
// Flush the queue
Expand Down Expand Up @@ -473,7 +473,7 @@ class ChatRenderer {
this.rootNode.appendChild(fragment);
}
if (this.scrollTracking) {
setImmediate(() => this.scrollToBottom());
setTimeout(() => this.scrollToBottom());
}
}
// Notify listeners that we have processed the batch
Expand Down
2 changes: 1 addition & 1 deletion tgui/packages/tgui-panel/panelFocus.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { focusMap } from 'tgui/focus';
// text you can select with the mouse.
const MIN_SELECTION_DISTANCE = 10;

const deferredFocusMap = () => setImmediate(() => focusMap());
const deferredFocusMap = () => setTimeout(() => focusMap());

export const setupPanelFocusHacks = () => {
let focusStolen = false;
Expand Down
Loading
Loading