[MIRROR] finish that up (#10340)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-03-09 16:12:15 -07:00
committed by GitHub
parent 075b5ce8d1
commit 41b5caff60
38 changed files with 157 additions and 62 deletions

View File

@@ -74,6 +74,7 @@ VIRGO3B_TURF_CREATE(/turf/simulated/floor/reinforced)
color = "#FFBBBB" color = "#FFBBBB"
/turf/simulated/sky/virgo3b/Initialize(mapload) /turf/simulated/sky/virgo3b/Initialize(mapload)
. = ..()
SSplanets.addTurf(src) SSplanets.addTurf(src)
set_light(2, 2, "#FFBBBB") set_light(2, 2, "#FFBBBB")

View File

@@ -16,6 +16,10 @@ const logger = createLogger('dreamseeker');
const instanceByPid = new Map(); const instanceByPid = new Map();
export class DreamSeeker { export class DreamSeeker {
pid: number;
addr: string;
client: any;
static getInstancesByPids: (pids: any) => Promise<any[]>;
constructor(pid, addr) { constructor(pid, addr) {
this.pid = pid; this.pid = pid;
this.addr = addr; this.addr = addr;
@@ -37,6 +41,8 @@ export class DreamSeeker {
} }
} }
type Entry = { pid: number; addr: string };
/** /**
* @param {number[]} pids * @param {number[]} pids
* @returns {DreamSeeker[]} * @returns {DreamSeeker[]}
@@ -45,8 +51,8 @@ DreamSeeker.getInstancesByPids = async (pids) => {
if (process.platform !== 'win32') { if (process.platform !== 'win32') {
return []; return [];
} }
const instances = []; const instances: any[] = [];
const pidsToResolve = []; const pidsToResolve: number[] = [];
for (let pid of pids) { for (let pid of pids) {
const instance = instanceByPid.get(pid); const instance = instanceByPid.get(pid);
if (instance) { if (instance) {
@@ -64,7 +70,7 @@ DreamSeeker.getInstancesByPids = async (pids) => {
}); });
// Line format: // Line format:
// proto addr mask mode pid // proto addr mask mode pid
const entries = []; const entries: Entry[] = [];
const lines = stdout.split('\r\n'); const lines = stdout.split('\r\n');
for (let line of lines) { for (let line of lines) {
const words = line.match(/\S+/g); const words = line.match(/\S+/g);

View File

@@ -16,13 +16,15 @@ const { parse: parseStackTrace } = require('stacktrace-parser');
const logger = createLogger('retrace'); const logger = createLogger('retrace');
type SourceMapData = { file: string; consumer: any };
const { SourceMapConsumer } = SourceMap; const { SourceMapConsumer } = SourceMap;
const sourceMaps = []; const sourceMaps: SourceMapData[] = [];
export const loadSourceMaps = async (bundleDir) => { export const loadSourceMaps = async (bundleDir) => {
// Destroy and garbage collect consumers // Destroy and garbage collect consumers
while (sourceMaps.length !== 0) { while (sourceMaps.length !== 0) {
const { consumer } = sourceMaps.shift(); const { consumer } = sourceMaps.shift() as SourceMapData;
consumer.destroy(); consumer.destroy();
} }
// Load new sourcemaps // Load new sourcemaps

View File

@@ -22,6 +22,11 @@ export { loadSourceMaps };
export const setupLink = () => new LinkServer(); export const setupLink = () => new LinkServer();
class LinkServer { class LinkServer {
wss: any;
httpServer: http.Server<
typeof http.IncomingMessage,
typeof http.ServerResponse
>;
constructor() { constructor() {
logger.log('setting up'); logger.log('setting up');
this.wss = null; this.wss = null;

View File

@@ -29,7 +29,7 @@ const SEARCH_LOCATIONS = [
`/mnt/c/Users/*/*/BYOND/cache`, `/mnt/c/Users/*/*/BYOND/cache`,
]; ];
let cacheRoot; let cacheRoot: string;
export const findCacheRoot = async () => { export const findCacheRoot = async () => {
if (cacheRoot) { if (cacheRoot) {
@@ -83,9 +83,10 @@ export const reloadByondCache = async (bundleDir) => {
return; return;
} }
// Get dreamseeker instances // Get dreamseeker instances
const pids = cacheDirs.map((cacheDir) => const pids = cacheDirs.map((cacheDir) => {
parseInt(cacheDir.split('/cache/tmp').pop(), 10), const ourDir = cacheDir.split('/cache/tmp').pop();
); return parseInt(ourDir ? ourDir : '', 10);
});
const dssPromise = DreamSeeker.getInstancesByPids(pids); const dssPromise = DreamSeeker.getInstancesByPids(pids);
// Copy assets // Copy assets
const assets = await resolveGlob( const assets = await resolveGlob(

View File

@@ -22,7 +22,7 @@ export const resolveGlob = (...sections) => {
silent: true, silent: true,
windowsPathsNoEscape: true, windowsPathsNoEscape: true,
}); });
const safePaths = []; const safePaths: string[] = [];
for (let path of unsafePaths) { for (let path of unsafePaths) {
try { try {
fs.statSync(path); fs.statSync(path);

View File

@@ -26,6 +26,9 @@ export const createCompiler = async (options) => {
}; };
class WebpackCompiler { class WebpackCompiler {
webpack: any;
config: any;
bundleDir: string;
async setup(options) { async setup(options) {
// Create a require context that is relative to project root // Create a require context that is relative to project root
// and retrieve all necessary dependencies. // and retrieve all necessary dependencies.

View File

@@ -4,7 +4,7 @@
* @license MIT * @license MIT
*/ */
import { Action, AnyAction, Dispatch, Middleware } from 'common/redux'; import type { Action, AnyAction, Dispatch, Middleware } from 'common/redux';
const EXCLUDED_PATTERNS = [/v4shim/i]; const EXCLUDED_PATTERNS = [/v4shim/i];
const loadedMappings: Record<string, string> = {}; const loadedMappings: Record<string, string> = {};

View File

@@ -5,7 +5,7 @@
*/ */
import { useState } from 'react'; import { useState } from 'react';
import { Flex, Section, Tabs } from 'tgui-core/components'; import { Section, Stack, Tabs } from 'tgui-core/components';
import { Pane, Window } from '../layouts'; import { Pane, Window } from '../layouts';
@@ -21,17 +21,17 @@ const r = require.context('../stories', false, /\.stories\.jsx$/);
*/ */
const getStories = () => r.keys().map((path) => r(path)); const getStories = () => r.keys().map((path) => r(path));
export const KitchenSink = (props) => { export const KitchenSink = (props: { panel: boolean }) => {
const { panel } = props; const { panel } = props;
const [theme] = useState(null); const [theme] = useState(undefined);
const [pageIndex, setPageIndex] = useState(0); const [pageIndex, setPageIndex] = useState(0);
const stories = getStories(); const stories = getStories();
const story = stories[pageIndex]; const story = stories[pageIndex];
const Layout = panel ? Pane : Window; const Layout = panel ? Pane : Window;
return ( return (
<Layout title="Kitchen Sink" width={600} height={500} theme={theme}> <Layout title="Kitchen Sink" width={600} height={500} theme={theme}>
<Flex height="100%"> <Stack fill>
<Flex.Item m={1} mr={0}> <Stack.Item m={1} mr={0}>
<Section fill fitted> <Section fill fitted>
<Tabs vertical> <Tabs vertical>
{stories.map((story, i) => ( {stories.map((story, i) => (
@@ -46,11 +46,11 @@ export const KitchenSink = (props) => {
))} ))}
</Tabs> </Tabs>
</Section> </Section>
</Flex.Item> </Stack.Item>
<Flex.Item position="relative" grow={1}> <Stack.Item position="relative" grow>
<Layout.Content scrollable>{story.meta.render()}</Layout.Content> <Layout.Content scrollable>{story.meta.render()}</Layout.Content>
</Flex.Item> </Stack.Item>
</Flex> </Stack>
</Layout> </Layout>
); );
}; };

View File

@@ -4,6 +4,7 @@
* @license MIT * @license MIT
*/ */
import type { AnyAction, Middleware } from 'common/redux';
import { globalEvents } from 'tgui-core/events'; import { globalEvents } from 'tgui-core/events';
import { acquireHotKey } from 'tgui-core/hotkeys'; import { acquireHotKey } from 'tgui-core/hotkeys';
import { KEY_BACKSPACE, KEY_F10, KEY_F11, KEY_F12 } from 'tgui-core/keycodes'; import { KEY_BACKSPACE, KEY_F10, KEY_F11, KEY_F12 } from 'tgui-core/keycodes';
@@ -20,15 +21,15 @@ const relayedTypes = [
'chat/message', 'chat/message',
]; ];
export const debugMiddleware = (store) => { export const debugMiddleware: Middleware = (store) => {
acquireHotKey(KEY_F11); acquireHotKey(KEY_F11);
acquireHotKey(KEY_F12); acquireHotKey(KEY_F12);
globalEvents.on('keydown', (key) => { globalEvents.on('keydown', (key) => {
if (key.code === KEY_F11) { if (key.code === KEY_F11) {
store.dispatch(toggleDebugLayout()); store.dispatch(toggleDebugLayout() as any);
} }
if (key.code === KEY_F12) { if (key.code === KEY_F12) {
store.dispatch(toggleKitchenSink()); store.dispatch(toggleKitchenSink() as any);
} }
if (key.ctrl && key.alt && key.code === KEY_BACKSPACE) { if (key.ctrl && key.alt && key.code === KEY_BACKSPACE) {
// NOTE: We need to call this in a timeout, because we need a clean // NOTE: We need to call this in a timeout, because we need a clean
@@ -45,7 +46,7 @@ export const debugMiddleware = (store) => {
return (next) => (action) => next(action); return (next) => (action) => next(action);
}; };
export const relayMiddleware = (store) => { export const relayMiddleware: Middleware = (store) => {
const devServer = require('tgui-dev-server/link/client.cjs'); const devServer = require('tgui-dev-server/link/client.cjs');
const externalBrowser = location.search === '?external'; const externalBrowser = location.search === '?external';
if (externalBrowser) { if (externalBrowser) {
@@ -62,12 +63,12 @@ export const relayMiddleware = (store) => {
acquireHotKey(KEY_F10); acquireHotKey(KEY_F10);
globalEvents.on('keydown', (key) => { globalEvents.on('keydown', (key) => {
if (key === KEY_F10) { if (key === KEY_F10) {
store.dispatch(openExternalBrowser()); store.dispatch(openExternalBrowser() as any);
} }
}); });
} }
return (next) => (action) => { return (next) => (action) => {
const { type, payload, relayed } = action; const { type, payload, relayed } = action as AnyAction;
if (type === openExternalBrowser.type) { if (type === openExternalBrowser.type) {
window.open(location.href + '?external', '_blank'); window.open(location.href + '?external', '_blank');
return; return;

View File

@@ -4,7 +4,11 @@
* @license MIT * @license MIT
*/ */
export const debugReducer = (state = {}, action) => { import type { ActionData } from './types';
type StateData = { kitchenSink: boolean; debugLayout: boolean };
export const debugReducer = (state = {} as StateData, action: ActionData) => {
const { type, payload } = action; const { type, payload } = action;
if (type === 'debug/toggleKitchenSink') { if (type === 'debug/toggleKitchenSink') {
return { return {

View File

@@ -0,0 +1 @@
export type ActionData = { type: string; payload: any; relayed: boolean };

View File

@@ -10,9 +10,23 @@ import { Box, Button, Image } from 'tgui-core/components';
import { Window } from './Window'; import { Window } from './Window';
type Header = { icon: string };
type Data = {
PC_device_theme: string;
PC_batteryicon: string;
PC_showbatteryicon: boolean;
PC_batterypercent: number;
PC_ntneticon: string;
PC_stationdate: string;
PC_stationtime: string;
PC_programheaders: Header[];
PC_showexitprogram: boolean;
};
export const NtosWindow = (props) => { export const NtosWindow = (props) => {
const { title, width = 575, height = 700, children } = props; const { title, width = 575, height = 700, children } = props;
const { act, data } = useBackend(); const { act, data } = useBackend<Data>();
const { const {
PC_device_theme, PC_device_theme,
PC_batteryicon, PC_batteryicon,

View File

@@ -0,0 +1,20 @@
/**
* @file
* @copyright 2021 Aleksej Komarov
* @license MIT
*/
import { Blink, Section } from 'tgui-core/components';
export const meta = {
title: 'Blink',
render: () => <Story />,
};
const Story = (props) => {
return (
<Section>
<Blink>Blink</Blink>
</Section>
);
};

View File

@@ -0,0 +1,24 @@
/**
* @file
* @copyright 2021 Aleksej Komarov
* @license MIT
*/
import { BlockQuote, Section } from 'tgui-core/components';
import { BoxWithSampleText } from './common';
export const meta = {
title: 'BlockQuote',
render: () => <Story />,
};
const Story = (props) => {
return (
<Section>
<BlockQuote>
<BoxWithSampleText />
</BlockQuote>
</Section>
);
};

View File

@@ -34,7 +34,6 @@ const Story = (props) => {
<Box mb={1}> <Box mb={1}>
<Button>Simple</Button> <Button>Simple</Button>
<Button selected>Selected</Button> <Button selected>Selected</Button>
<Button altSelected>Alt Selected</Button>
<Button disabled>Disabled</Button> <Button disabled>Disabled</Button>
<Button color="transparent">Transparent</Button> <Button color="transparent">Transparent</Button>
<Button icon="cog">Icon</Button> <Button icon="cog">Icon</Button>

View File

@@ -6,7 +6,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { logger } from 'tgui/logging'; import { logger } from 'tgui/logging';
import { Box, Button, ByondUi, Section } from 'tgui-core/components'; import { Button, ByondUi, Section, TextArea } from 'tgui-core/components';
export const meta = { export const meta = {
title: 'ByondUi', title: 'ByondUi',
@@ -52,14 +52,13 @@ const Story = (props) => {
</Button> </Button>
} }
> >
<Box <TextArea
as="textarea"
width="100%" width="100%"
height="10em" height="10em"
onChange={(e) => setCode(e.target.value)} onChange={(_, value) => setCode(value)}
> >
{code} {code}
</Box> </TextArea>
</Section> </Section>
</> </>
); );

View File

@@ -23,23 +23,28 @@ const Story = (props) => {
const [progress, setProgress] = useState(0.5); const [progress, setProgress] = useState(0.5);
const [color, setColor] = useState(''); const [color, setColor] = useState('');
const color_data = color
? { color: color }
: {
ranges: {
good: [0.5, Infinity],
bad: [-Infinity, 0.1],
average: [0, 0.5],
},
};
return ( return (
<Section> <Section>
<ProgressBar {...color_data} minValue={-1} maxValue={1} value={progress}> {color ? (
Value: {Number(progress).toFixed(1)} <ProgressBar color={color} minValue={-1} maxValue={1} value={progress}>
</ProgressBar> Value: {Number(progress).toFixed(1)}
<Box mt={1}> </ProgressBar>
<LabeledList mt="2em"> ) : (
<ProgressBar
ranges={{
good: [0.5, Infinity],
bad: [-Infinity, 0.1],
average: [0, 0.5],
}}
minValue={-1}
maxValue={1}
value={progress}
>
Value: {Number(progress).toFixed(1)}
</ProgressBar>
)}
<Box mt={1} mb="2em">
<LabeledList>
<LabeledList.Item label="Adjust value"> <LabeledList.Item label="Adjust value">
<Button onClick={() => setProgress(progress - 0.1)}>-0.1</Button> <Button onClick={() => setProgress(progress - 0.1)}>-0.1</Button>
<Button onClick={() => setProgress(progress + 0.1)}>+0.1</Button> <Button onClick={() => setProgress(progress + 0.1)}>+0.1</Button>

View File

@@ -12,10 +12,19 @@ export const meta = {
render: () => <Story />, render: () => <Story />,
}; };
type TabProps = {
vertical: boolean;
leftSlot: boolean;
rightSlot: boolean;
icon: boolean;
fluid: boolean;
centered: boolean;
};
const TAB_RANGE = ['Tab #1', 'Tab #2', 'Tab #3', 'Tab #4']; const TAB_RANGE = ['Tab #1', 'Tab #2', 'Tab #3', 'Tab #4'];
const Story = (props) => { const Story = (props) => {
const [tabProps, setTabProps] = useState({}); const [tabProps, setTabProps] = useState({} as TabProps);
return ( return (
<> <>
<Section> <Section>
@@ -93,23 +102,23 @@ const Story = (props) => {
</Button.Checkbox> </Button.Checkbox>
</Section> </Section>
<Section fitted> <Section fitted>
<TabsPrefab /> <TabsPrefab tabProps={tabProps} />
</Section> </Section>
<Section title="Normal section"> <Section title="Normal section">
<TabsPrefab /> <TabsPrefab tabProps={tabProps} />
Some text Some text
</Section> </Section>
<Section> <Section>
Section-less tabs appear the same as tabs in a fitted section: Section-less tabs appear the same as tabs in a fitted section:
</Section> </Section>
<TabsPrefab /> <TabsPrefab tabProps={tabProps} />
</> </>
); );
}; };
const TabsPrefab = (props) => { const TabsPrefab = (props: { tabProps: TabProps }) => {
const [tabIndex, setTabIndex] = useState(0); const [tabIndex, setTabIndex] = useState(0);
const [tabProps] = useState({}); const { tabProps } = props;
return ( return (
<Tabs <Tabs
vertical={tabProps.vertical} vertical={tabProps.vertical}
@@ -120,7 +129,7 @@ const TabsPrefab = (props) => {
<Tabs.Tab <Tabs.Tab
key={i} key={i}
selected={i === tabIndex} selected={i === tabIndex}
icon={tabProps.icon && 'info-circle'} icon={tabProps.icon ? 'info-circle' : undefined}
leftSlot={ leftSlot={
tabProps.leftSlot && ( tabProps.leftSlot && (
<Button circular compact color="transparent" icon="times" /> <Button circular compact color="transparent" icon="times" />

View File

@@ -4,24 +4,25 @@
* @license MIT * @license MIT
*/ */
import { useState } from 'react';
import { Input, LabeledList, Section } from 'tgui-core/components'; import { Input, LabeledList, Section } from 'tgui-core/components';
export const meta = { export const meta = {
title: 'Themes', title: 'Themes',
render: () => <Story />, render: (theme, setTheme) => <Story theme={theme} setTheme={setTheme} />,
}; };
const Story = (props) => { const Story = (props: {
const [theme, setTheme] = useState('kitchenSinkTheme'); readonly theme: string;
readonly setTheme: Function;
}) => {
return ( return (
<Section> <Section>
<LabeledList> <LabeledList>
<LabeledList.Item label="Use theme"> <LabeledList.Item label="Use theme">
<Input <Input
placeholder="theme_name" placeholder="theme_name"
value={theme} value={props.theme}
onInput={(e, value) => setTheme(value)} onInput={(e, value) => props.setTheme(value)}
/> />
</LabeledList.Item> </LabeledList.Item>
</LabeledList> </LabeledList>