Adds an event debugging window for real time midround event data

This commit is contained in:
Migratingcocofruit
2025-08-22 23:13:44 +03:00
parent 3acbf6470f
commit ecd99a6c9e
8 changed files with 293 additions and 4 deletions
+13
View File
@@ -91,3 +91,16 @@ SUBSYSTEM_DEF(debugview)
popup.set_content(html.Join("<br>"))
popup.open(FALSE)
// Make a verb for dumping full SS stats
/client/proc/event_debug()
set name = "Event Debug"
set category = "Debug"
if(!check_rights(R_DEBUG|R_VIEWRUNTIMES))
return
var/datum/ui_module/admin/event_debug/event_debug_window = get_admin_ui_module(/datum/ui_module/admin/event_debug)
event_debug_window.ui_interact(usr)
+2
View File
@@ -171,6 +171,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
/client/proc/uid_log,
/client/proc/reestablish_db_connection,
/client/proc/ss_breakdown,
/client/proc/event_debug,
#ifdef REFERENCE_TRACKING
/datum/proc/find_refs,
/datum/proc/qdel_then_find_references,
@@ -266,6 +267,7 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
/client/proc/cmd_display_del_log_simple,
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
/client/proc/ss_breakdown,
/client/proc/event_debug,
/client/proc/show_gc_queues,
/client/proc/debug_global_variables,
/client/proc/debug_timers,
@@ -0,0 +1,49 @@
RESTRICT_TYPE(/datum/ui_module/admin/event_debug)
/datum/ui_module/admin/event_debug
name = "Event Debug Screen"
var/list/cached_data
COOLDOWN_DECLARE(cache_cooldown)
/datum/ui_module/admin/event_debug/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "EventDebug", name)
ui.set_autoupdate(FALSE)
ui.open()
/datum/ui_module/admin/event_debug/ui_data(mob/user)
if(COOLDOWN_FINISHED(src, cache_cooldown))
update_cached_data()
COOLDOWN_START(src, cache_cooldown, 1 SECONDS)
return cached_data
/datum/ui_module/admin/event_debug/proc/update_cached_data()
var/list/data = list()
var/resources = get_total_resources()
for(var/resource in resources)
data["resources"] += list(list("name" = resource, "amount" = resources[resource]))
var/net_resources = number_active_with_role()
for(var/resource in net_resources)
data["net_resources"] += list(list("name" = resource, "amount" = net_resources[resource]))
data["containers"] = list()
for(var/datum/event_container/container in SSevents.event_containers)
var/list/container_data = list()
container_data["severity"] = GLOB.severity_to_string[container.severity]
var/list/events = list()
for(var/datum/event_meta/meta_event in container.available_events)
events += list(list("name" = meta_event.skeleton.name, "weight" = meta_event.get_weight(resources)))
container_data["events"] = events
data["containers"] += list(container_data)
cached_data = data
/datum/ui_module/admin/event_debug/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
switch(action)
if("refresh")
return TRUE
+1 -1
View File
@@ -70,7 +70,7 @@
active_with_role = SSevents.debug_resources.Copy()
for(var/mob/M in GLOB.player_list)
if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive
if(!M.mind?.assigned_role || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive
continue
if(M.mind.assigned_role in (GLOB.exp_jobsmap[EXP_TYPE_CREW]["titles"]))
+1
View File
@@ -1609,6 +1609,7 @@
#include "code\modules\admin\watchlist.dm"
#include "code\modules\admin\db_ban\functions.dm"
#include "code\modules\admin\menus\antagonist_menu.dm"
#include "code\modules\admin\menus\event_debug_menu.dm"
#include "code\modules\admin\menus\ui_module_admin.dm"
#include "code\modules\admin\permissionverbs\permissionedit.dm"
#include "code\modules\admin\tickets\adminticketsverbs.dm"
@@ -1,9 +1,9 @@
import { createContext, useContext } from 'react';
import { Box, Button, Flex, Icon, Section, Stack, Table, Tabs } from 'tgui-core/components';
import { BooleanLike, classes } from 'tgui-core/react';
import { useBackend } from '../backend';
import { Window } from '../layouts';
import { BooleanLike, classes } from 'tgui-core/react';
import { createContext, useContext } from 'react';
const Dir = {
NORTH: 1,
@@ -0,0 +1,224 @@
import { createContext, useContext, useState } from 'react';
import { Button, Section, Stack, Table, Tabs } from 'tgui-core/components';
import { useBackend } from '../backend';
import { Window } from '../layouts';
interface EventData {
containers: EventContainer[];
resources: Resource[];
net_resources: Resource[];
}
interface EventContainer {
severity: String;
events: Event[];
}
interface Event {
name: String;
weight: number;
}
interface Resource {
name: String;
amount: number;
}
type EventTabContextType = {
tabIndexState: [number, (value: number) => void];
};
const EventTabContext = createContext<EventTabContextType>({
tabIndexState: [1, () => {}],
});
export const EventDebug = () => {
const tabIndexState = useState(1);
return (
<Window width={800} height={600}>
<Window.Content>
<EventTabContext.Provider value={{ tabIndexState }}>
<Stack vertical>
<Stack.Item>
<EventDebugNavigation />
</Stack.Item>
<Stack.Item grow>
<EventDebugContent />
</Stack.Item>
</Stack>
</EventTabContext.Provider>
</Window.Content>
</Window>
);
};
const EventDebugNavigation = () => {
const { tabIndexState } = useContext<EventTabContextType>(EventTabContext);
const [tabIndex, settabIndex] = tabIndexState;
return (
<Tabs>
<Tabs.Tab
key="Mundane"
selected={tabIndex === 0}
onClick={() => {
settabIndex(0);
}}
>
Mundane
</Tabs.Tab>
<Tabs.Tab
key="Moderate"
selected={tabIndex === 1}
onClick={() => {
settabIndex(1);
}}
>
Moderate
</Tabs.Tab>
<Tabs.Tab
key="Major"
selected={tabIndex === 2}
onClick={() => {
settabIndex(2);
}}
>
Major
</Tabs.Tab>
<Tabs.Tab
key="Disaster"
selected={tabIndex === 3}
onClick={() => {
settabIndex(3);
}}
>
Disaster
</Tabs.Tab>
<Tabs.Tab
key="Resource Data"
selected={tabIndex === 4}
onClick={() => {
settabIndex(4);
}}
>
Resource Data
</Tabs.Tab>
</Tabs>
);
};
const PickTitle = (index) => {
switch (index) {
case 0:
return 'Mundane';
case 1:
return 'Moderate';
case 2:
return 'Major';
case 3:
return 'Disaster';
case 4:
return 'Resource Data';
default:
return 'Something went wrong with this menu, make an issue report please!';
}
};
const PickTab = (index) => {
switch (index) {
case 0:
return <EventContainerData severity="Mundane" />;
case 1:
return <EventContainerData severity="Moderate" />;
case 2:
return <EventContainerData severity="Major" />;
case 3:
return <EventContainerData severity="Disaster" />;
case 4:
return <ResourceData />;
default:
return 'Something went wrong with this menu, make an issue report please!';
}
};
const EventDebugContent = () => {
const { act } = useBackend<EventData>();
const { tabIndexState } = useContext<EventTabContextType>(EventTabContext);
const [tabIndex, settabIndex] = tabIndexState;
return (
<Section
fill
title={PickTitle(tabIndex)}
buttons={
<Stack fill>
<Button icon="sync" onClick={() => act('refresh')}>
Refresh
</Button>
</Stack>
}
>
<EventDebugContent2 />
</Section>
);
};
const EventDebugContent2 = () => {
const { tabIndexState } = useContext<EventTabContextType>(EventTabContext);
const [tabIndex, settabIndex] = tabIndexState;
return PickTab(tabIndex);
};
const EventContainerData = (properties) => {
const { act, data } = useBackend<EventData>();
const { containers } = data;
const { severity } = properties;
if (!containers) {
return 'Missing containers data for: ' + severity;
}
let container_index: number = 0;
for (let i = 0; i < containers.length; i++) {
if (containers[i].severity === severity) {
container_index = i;
}
}
return (
<Table className="Event Container Info">
{containers[container_index].events.map((event, index) => (
<Table.Row key={index}>
<Table.Cell>{event.name}</Table.Cell>
<Table.Cell>{event.weight}</Table.Cell>
</Table.Row>
))}
</Table>
);
};
const ResourceData = () => {
const { data } = useBackend<EventData>();
const { resources, net_resources } = data;
return (
<Stack vertical>
<Section title="Net Resources">
<Table>
{net_resources.map((resource, index) => (
<Table.Row key={index}>
<Table.Cell>{resource.name}</Table.Cell>
<Table.Cell>{resource.amount}</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
<Section title="Total Resources">
<Table>
{resources.map((resource, index) => (
<Table.Row key={index}>
<Table.Cell>{resource.name}</Table.Cell>
<Table.Cell>{resource.amount}</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
</Stack>
);
};
File diff suppressed because one or more lines are too long