Initial codebase

This commit is contained in:
Aslan 2025-11-17 09:38:57 -05:00
commit e09210f3e0
47 changed files with 2645 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules/
dist/
save.json

1209
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

25
package.json Normal file
View file

@ -0,0 +1,25 @@
{
"name": "tech-tycoon-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"build": "npx tsc",
"start": "npx tsc && node dist/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^5.1.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
"@types/express": "^5.0.5",
"@types/node": "^24.10.1",
"ts-node": "^10.9.2",
"typescript": "^5.9.3"
}
}

4
src/config.json Normal file
View file

@ -0,0 +1,4 @@
{
"port": 2142,
"savepath": "save.json"
}

3
src/consts.ts Normal file
View file

@ -0,0 +1,3 @@
const WORKBENCH_SIZE = 999;
export { WORKBENCH_SIZE };

View file

@ -0,0 +1,20 @@
import { Router, type Request, type Response } from "express";
import type { ISetTimeRequest } from "./types.js";
import state from "../../state/state.js";
const router = Router();
router.post("/settime", (req: Request, res: Response) => {
console.log(req.body);
let request: ISetTimeRequest = req.body;
state.time = request.time;
res.json({
message: "ok",
});
});
export default router;

View file

@ -0,0 +1,5 @@
interface ISetTimeRequest {
time: number;
}
export { type ISetTimeRequest };

View file

@ -0,0 +1,15 @@
import { Router, type Request, type Response } from "express";
import state from "../../state/state.js";
const router = Router();
router.get("/time", (req: Request, res: Response) => {
res.json(state.time);
});
router.get("/player", (req: Request, res: Response) => {
res.json(state.player);
});
export default router;

View file

@ -0,0 +1,13 @@
import { Router, type Request, type Response } from "express";
import websites from "../../data/websites.js";
import state from "../../state/state.js";
const router = Router();
router.get("/websites", (req: Request, res: Response) => {
res.json(websites);
});
export default router;

View file

@ -0,0 +1,39 @@
import { Router, type Request, type Response } from "express";
import state from "../../state/state.js";
import type { MoveParams, MoveRequest } from "./types.js";
import { MoveInventory } from "../../services/inventory/inventory.js";
const router = Router();
router.get("/player", (req: Request, res: Response) => {
res.json(state.player.inventory);
});
router.get("/car", (req: Request, res: Response) => {
res.json(state.car.inventory);
});
router.get("/home", (req: Request, res: Response) => {
res.json(state.home.inventory);
});
router.post("/move/:id", (req: Request<MoveParams>, res: Response) => {
const id = req.params.id;
const request = req.body as MoveRequest;
const error = MoveInventory(id, request.source, request.destination, state);
if (error) {
res.json({
message: "error",
error: error,
});
return;
}
res.json({
message: "ok",
});
});
export default router;

View file

@ -0,0 +1,10 @@
interface MoveParams {
id: number;
}
interface MoveRequest {
source: "player" | "car" | "home";
destination: "player" | "car" | "home" | "workbench";
}
export { type MoveParams, type MoveRequest };

View file

@ -0,0 +1,26 @@
import { Router, type Request, type Response } from "express";
import state from "../../state/state.js";
import type { IdParams } from "./types.js";
const router = Router();
router.get("/", (req: Request, res: Response) => {
res.json(state.shops);
});
router.get("/:id", (req: Request<IdParams>, res: Response) => {
let shop = state.shops[req.params.id];
if (shop !== undefined) {
res.json(shop);
return;
}
res.json({
message: "error",
error: `shop with id ${req.params.id} doesn't exist`,
});
});
export default router;

View file

@ -0,0 +1,5 @@
interface IdParams {
id: number;
}
export { type IdParams };

View file

@ -0,0 +1,62 @@
import { Router, type Request, type Response } from "express";
import { readFile, writeFile } from "fs";
import { game } from "../../state/state.js";
import config from "../../config.json" with { type: "json" };
const router = Router();
router.get("/load", (req: Request, res: Response) => {
readFile(config.savepath, "utf8", (err, data) => {
if (err) {
res.json({
message: "error",
error: err.message,
});
return;
}
Object.assign(game.state, JSON.parse(data));
res.json({
message: "ok",
});
});
});
router.get("/save", (req: Request, res: Response) => {
writeFile(config.savepath, JSON.stringify(game.state), "utf8", (err) => {
if (err) {
res.json({
message: "error",
error: err.message,
});
return;
}
res.json({
message: "ok",
});
});
});
router.get("/stop", (req: Request, res: Response) => {
writeFile(config.savepath, JSON.stringify(game.state), "utf8", (err) => {
if (err) {
res.json({
message: "error",
error: err.message,
});
return;
}
res.json({
message: "ok",
});
process.exit(0);
});
});
export default router;

View file

@ -0,0 +1,22 @@
import { Router, type Request, type Response } from "express";
import state from "../../state/state.js";
import cpus from "../../data/items/cpus.js";
const router = Router();
router.get("/ping", (req: Request, res: Response) => {
res.json({ message: "pong!" });
});
router.get("/test", (req: Request, res: Response) => {
let testItem = cpus[0];
if (testItem !== undefined) {
state.home.inventory.items.push(testItem);
}
res.json({ message: "test" });
});
export default router;

View file

@ -0,0 +1,10 @@
interface InstallMotherboardParams {
motherboardId: number;
caseId: number;
}
interface RemoveMotherboardParams {
caseId: number;
}
export { type InstallMotherboardParams, type RemoveMotherboardParams };

View file

@ -0,0 +1,60 @@
import { Router, type Request, type Response } from "express";
import state from "../../state/state.js";
import type {
InstallMotherboardParams,
RemoveMotherboardParams,
} from "./types.js";
import {
InstallMotherboard,
RemoveMotherboard,
} from "../../services/workbench/workbench.js";
const router = Router();
router.get("/devices", (req: Request, res: Response) => {
res.json(state.home.workbench.devices);
});
router.post(
"/install/motherboard/:motherboardId/:caseId",
(req: Request<InstallMotherboardParams>, res: Response) => {
const motherboardId = req.params.motherboardId;
const caseId = req.params.caseId;
const error = InstallMotherboard(motherboardId, caseId, state);
if (error) {
res.json({
message: "error",
error: error,
});
return;
}
res.json({
message: "ok",
});
},
);
router.post(
"/remove/motherboard/:caseId",
(req: Request<RemoveMotherboardParams>, res: Response) => {
const caseId = req.params.caseId;
const error = RemoveMotherboard(caseId, state);
if (error) {
res.json({
message: "error",
error: error,
});
return;
}
res.json({
message: "ok",
});
},
);
export default router;

7
src/data/items.ts Normal file
View file

@ -0,0 +1,7 @@
import { type IItem } from "../state/item.js";
import cpus from "./items/cpus.js";
import gpus from "./items/gpus.js";
import other from "./items/other.js";
export default [...cpus, ...gpus, ...other] as IItem[];

15
src/data/items/cases.ts Normal file
View file

@ -0,0 +1,15 @@
import { FormFactorType, ItemType, type ICase } from "../../state/item.js";
export default [
{
type: ItemType.CASE,
name: "DIY Case",
formFactor: FormFactorType.E_ATX,
width: 60,
height: 70,
depth: 20,
installedDevices: [],
manufacturer: "Player",
durability: 100,
},
] as ICase[];

31
src/data/items/cpus.ts Normal file
View file

@ -0,0 +1,31 @@
import { SocketType } from "../../state/cpu.js";
import { ItemType, type ICPU } from "../../state/item.js";
export default [
{
name: "Intel Core i3-3220",
type: ItemType.CPU,
durability: 98,
cores: [
{
clockSpeed: 3400,
originalClockSpeed: 3400,
threads: 2,
cacheL1: 2000,
cacheL2: 8000,
},
{
clockSpeed: 3400,
originalClockSpeed: 3400,
threads: 2,
cacheL1: 2000,
cacheL2: 8000,
},
],
cacheL3: 4000000,
socket: SocketType.INTEL_LGA_1155,
process: 22,
tdp: 80,
price: 200,
},
] as ICPU[];

3
src/data/items/gpus.ts Normal file
View file

@ -0,0 +1,3 @@
import { ItemType, type IGPU } from "../../state/item.js";
export default [] as IGPU[];

View file

@ -0,0 +1,25 @@
import { SocketType } from "../../state/cpu.js";
import {
FormFactorType,
ItemType,
type IMotherboard,
} from "../../state/item.js";
import { MemoryType } from "../../state/memory.js";
export default [
{
type: ItemType.MOTHERBOARD,
name: "Generic Motherboard",
formFactor: FormFactorType.ATX,
socketCount: 1,
socket: SocketType.INTEL_LGA_1155,
memoryType: MemoryType.DDR3,
memorySlots: 2,
installedCPUs: [],
installedRAMs: [],
installedDevices: [],
connectors: [],
durability: 100,
canFitInComputerCase: true,
},
] as IMotherboard[];

11
src/data/items/other.ts Normal file
View file

@ -0,0 +1,11 @@
import { ItemType, type IItem, type IScrewdriver } from "../../state/item.js";
export default [
{
type: ItemType.SCREWDRIVER,
name: "Basic screwdriver",
quality: 1,
durability: 100,
price: 5,
} as IScrewdriver,
] as IItem[];

22
src/data/items/psus.ts Normal file
View file

@ -0,0 +1,22 @@
import { ConnectorType } from "../../state/connector.js";
import { FormFactorType, ItemType, type IPSU } from "../../state/item.js";
export default [
{
type: ItemType.PSU,
name: "Generic PSU",
formFactor: FormFactorType.ATX,
connectors: [
ConnectorType.SATA_POWER,
ConnectorType.SATA_POWER,
ConnectorType.PCI_POWER_4,
ConnectorType.PCI_POWER_4,
ConnectorType.PCI_POWER_6,
],
width: 15,
height: 10,
depth: 15,
wattage: 300,
durability: 100,
},
] as IPSU[];

15
src/data/items/rams.ts Normal file
View file

@ -0,0 +1,15 @@
import { ItemType, type IRAMModule } from "../../state/item.js";
import { MemoryType } from "../../state/memory.js";
export default [
{
type: ItemType.RAM_MODULE,
name: "Generic RAM",
memoryType: MemoryType.DDR3,
originalClockSpeed: 1600,
clockSpeed: 1800,
capacity: 2,
tdp: 5,
durability: 100,
},
] as IRAMModule[];

8
src/data/shops.ts Normal file
View file

@ -0,0 +1,8 @@
import type { IShop } from "../state/types.js";
export default [
{
name: "General Store",
items: [],
},
] as IShop[];

5
src/data/software.ts Normal file
View file

@ -0,0 +1,5 @@
import { type ISoftware } from "../state/software.js";
import os from "./software/os.js";
export default [...os] as ISoftware[];

11
src/data/software/os.ts Normal file
View file

@ -0,0 +1,11 @@
import { SoftwareType, type ISoftware } from "../../state/software.js";
export default [
{
type: SoftwareType.OS,
name: "Fedora 42",
cpuUsage: 200000000,
memoryUsage: 1000000000,
storageUsage: 10000000000,
},
] as ISoftware[];

12
src/data/websites.ts Normal file
View file

@ -0,0 +1,12 @@
import { readFileSync } from "fs";
import type { IWebsite } from "../state/types.js";
export default [
{
name: "Portal",
ip: "123.123.123.123",
domain: "portal.org",
html: readFileSync("src/data/websites/portal.org.html").toString(),
},
] as IWebsite[];

View file

@ -0,0 +1,12 @@
<html>
<head>
<title>Portal</title>
</head>
<body>
<h2>Portal</h2>
<ul>
<li><a href="portal.org">Portal</a></li>
<li><a href="">ShopCenter</a></li>
</ul>
</body>
</html>

137
src/helpers.ts Normal file
View file

@ -0,0 +1,137 @@
import { WORKBENCH_SIZE } from "./consts.js";
import { ItemType, type IItem, type IScrewdriver } from "./state/item.js";
import type { IInventory, IState, IWorkbench } from "./state/types.js";
type AllInventories = "player" | "car" | "home" | "workbench";
interface ItemContainer<T> {
index: number;
item: T;
}
const GetItemsAsInventory = (items: IItem[]): IInventory => {
return {
size: -1,
items: items,
};
};
const GetWorkbenchAsInventory = (workbench: IWorkbench): IInventory => {
return {
size: WORKBENCH_SIZE,
items: workbench.devices,
};
};
const GetInventory = (name: AllInventories, state: IState): IInventory => {
let inventory: IInventory;
switch (name) {
case "player":
inventory = state.player.inventory;
break;
case "car":
inventory = state.car.inventory;
break;
case "home":
inventory = state.home.inventory;
break;
case "workbench":
inventory = GetWorkbenchAsInventory(state.home.workbench);
break;
}
return inventory;
};
const GetItemsOfType = <T>(
itemType: ItemType,
inventories: IInventory[],
): T[] => {
const items: T[] = [];
inventories.forEach((inventory) => {
items.push(
...(inventory.items.filter(
(item) => item.type === itemType,
) as T[]),
);
});
return items;
};
const GetItemOfType = <T>(
itemType: ItemType,
inventories: IInventory[],
): T | undefined => {
let item: T | undefined;
inventories.forEach((inventory) => {
const found = inventory.items.find(
(_item) => _item.type === itemType,
) as T;
if (found) {
item = found;
return;
}
});
return item;
};
const GetItemContainerOfType = <T>(
itemType: ItemType,
inventories: IInventory[],
): ItemContainer<T> | undefined => {
let container: ItemContainer<T> | undefined;
inventories.forEach((inventory) => {
const found = inventory.items.find(
(_item) => _item.type === itemType,
) as T;
const foundIndex = inventory.items.findIndex(
(_item) => _item.type === itemType,
);
if (found && foundIndex) {
container = {
index: foundIndex,
item: found,
};
return;
}
});
return container;
};
const GetBestScrewdriver = (
inventories: IInventory[],
): IScrewdriver | undefined => {
const screwdrivers = GetItemsOfType(
ItemType.SCREWDRIVER,
inventories,
) as IScrewdriver[];
let bestScrewdriver: IScrewdriver | undefined;
let bestQuality = -1;
screwdrivers.forEach((screwdriver) => {
if (screwdriver.quality > bestQuality) {
bestScrewdriver = screwdriver;
}
});
return bestScrewdriver;
};
export { type AllInventories, type ItemContainer };
export {
GetItemsAsInventory,
GetWorkbenchAsInventory,
GetInventory,
GetItemsOfType,
GetItemOfType,
GetItemContainerOfType,
GetBestScrewdriver,
};

31
src/index.ts Normal file
View file

@ -0,0 +1,31 @@
import express from "express";
import cors from "cors";
import config from "./config.json" with { type: "json" };
import testRoute from "./controllers/test/test.js";
import adminRoute from "./controllers/admin/admin.js";
import stateRoute from "./controllers/state/state.js";
import gameRoute from "./controllers/game/game.js";
import inventoryRoute from "./controllers/inventory/inventory.js";
import shopRoute from "./controllers/shop/shop.js";
import workbenchRoute from "./controllers/workbench/workbench.js";
import internetRoute from "./controllers/internet/internet.js";
const app = express();
app.use(express.json());
app.use(cors());
app.use("/test", testRoute);
app.use("/admin", adminRoute);
app.use("/state", stateRoute);
app.use("/game", gameRoute);
app.use("/inventory", inventoryRoute);
app.use("/shop", shopRoute);
app.use("/workbench", workbenchRoute);
app.use("/internet", internetRoute);
app.listen(config.port, () => {
console.log(`Server running at http://localhost:${config.port}`);
});

View file

@ -0,0 +1,25 @@
import { GetInventory, type AllInventories } from "../../helpers.js";
import type { IState } from "../../state/types.js";
const MoveInventory = (
id: number,
sourceName: AllInventories,
destinationName: AllInventories,
state: IState,
): string | undefined => {
const source = GetInventory(sourceName, state);
const destination = GetInventory(destinationName, state);
if (source.items[id] === undefined) {
return "source item doesn't exist";
}
if (destination.items.length >= destination.size) {
return "destination full";
}
destination.items.push(source.items[id]);
source.items.splice(id, 1);
};
export { MoveInventory };

View file

@ -0,0 +1,87 @@
import {
GetBestScrewdriver,
GetItemContainerOfType,
GetItemOfType,
GetItemsAsInventory,
GetItemsOfType,
GetWorkbenchAsInventory,
} from "../../helpers.js";
import { ItemType, type ICase, type IMotherboard } from "../../state/item.js";
import type { IState } from "../../state/types.js";
const InstallMotherboard = (
motherboardId: number,
caseId: number,
state: IState,
): string | undefined => {
const workbench = state.home.workbench;
const screwdriver = GetBestScrewdriver([
GetWorkbenchAsInventory(workbench),
state.player.inventory,
]);
if (!screwdriver) {
return "a screwdriver is required";
}
const itemCase = workbench.devices[caseId];
if (!itemCase || itemCase.type !== ItemType.CASE) {
return "there is no case in that inventory slot";
}
const pcCase = itemCase as ICase;
const itemMotherboard = workbench.devices[motherboardId];
if (!itemMotherboard || itemMotherboard.type !== ItemType.MOTHERBOARD) {
return "there is no motherboard in that inventory slot";
}
const motherboard = itemMotherboard as IMotherboard;
const existingMotherboard = GetItemOfType<IMotherboard>(
ItemType.MOTHERBOARD,
[GetItemsAsInventory(pcCase.installedDevices)],
);
if (existingMotherboard) {
return "there is already a motherboard installed in that case";
}
if (!motherboard.canFitInComputerCase) {
return "this item cannot fit inside a pc case";
}
pcCase.installedDevices.push(motherboard);
workbench.devices.splice(motherboardId, 1);
};
const RemoveMotherboard = (
caseId: number,
state: IState,
): string | undefined => {
const workbench = state.home.workbench;
const screwdriver = GetBestScrewdriver([
GetWorkbenchAsInventory(workbench),
state.player.inventory,
]);
if (!screwdriver) {
return "a screwdriver is required";
}
const itemCase = workbench.devices[caseId];
if (!itemCase || itemCase.type !== ItemType.CASE) {
return "there is no case in that inventory slot";
}
const pcCase = itemCase as ICase;
const motherboard = GetItemContainerOfType<IMotherboard>(
ItemType.MOTHERBOARD,
[GetItemsAsInventory(pcCase.installedDevices)],
);
if (!motherboard) {
return "there is no motherboard installed in that case";
}
workbench.devices.push(motherboard.item);
pcCase.installedDevices.splice(motherboard.index, 1);
};
export { InstallMotherboard, RemoveMotherboard };

57
src/state/company.ts Normal file
View file

@ -0,0 +1,57 @@
export enum Company {
Intel,
AMD,
Nvidia,
Seagate,
WD,
GSkill,
NZXT,
EK,
Alphacool,
EVGA,
Kingston,
Motorola,
Nikon,
Canon,
Qualcomm,
TSMC,
Samsung,
Apple,
Microsoft,
Canonical,
Amazon,
Meta,
Google,
HP,
Lenovo,
Vivo,
Huawei,
Cisco,
Asus,
Acer,
Sony,
LG,
HTC,
OnePlus,
Xiaomi,
Gigabyte,
Nokia,
HMD,
DELL,
FrameWork,
Tencent,
RODE,
RME,
Fiio,
Sennheiser,
Beyerdynamic,
Audeze,
Pine64,
Nintendo,
Nubia,
ZTE,
Nothing,
Essential,
Fairphone,
Razer,
}

29
src/state/connector.ts Normal file
View file

@ -0,0 +1,29 @@
export enum ConnectorType {
USB1,
USB2,
USB3,
USB4,
USBC1,
USBC2,
USBC3,
USBC4,
MOLEX,
SATA_POWER,
SATA1,
SATA2,
SATA3,
AGP,
PCI_POWER_4,
PCI_POWER_6,
PCI_POWER_8,
PCI,
PCIE,
PCIE2,
PCIE3,
PCIE4,
PCIE5,
PCIE6,
PCIE7,
PCIE8,
PCIE9,
}

32
src/state/cpu.ts Normal file
View file

@ -0,0 +1,32 @@
export enum CPUArchitecture {
M_6502,
M_6800,
M_6809,
M_680X0,
I_8080,
I_8051,
Z80,
SPARC,
MIPS,
POWER_PC,
x86,
x86_64,
Itanium,
ARMv7,
ARMv8,
ARMv9,
RISC_V,
LoongArch,
}
export enum CPUFeatures {
AVX,
AVX2,
AVX512,
}
export enum SocketType {
INTEL_LGA_1155,
INTEL_LGA_1156,
INTEL_LGA_2011,
}

37
src/state/gpu.ts Normal file
View file

@ -0,0 +1,37 @@
export enum GPUArchitecture {
Fahrenheit,
Celsius,
Kelvin,
Rankine,
Curie,
Tesla,
Fermi,
Kepler,
Maxwell,
Maxwell2,
Pascal,
Turing,
Volta,
Ampere,
Lovelace,
Hopper,
Blackwell,
Rubin,
TeraScale,
TeraScale2,
TeraScale3,
CGN,
CGN2,
CGN3,
CGN4,
CGN5,
RDNA,
RDNA2,
RDNA3,
RDNA3_5,
RDNA4,
CDNA,
CDNA2,
CDNA3,
UDNA,
}

212
src/state/item.ts Normal file
View file

@ -0,0 +1,212 @@
import type { Company } from "./company.js";
import type { ConnectorType } from "./connector.js";
import type { SocketType } from "./cpu.js";
import type { MemoryType } from "./memory.js";
import type { DiscType, DiskType, IStorage } from "./storage.js";
import type { INet } from "./types.js";
export enum ItemType {
SCREWDRIVER,
CPU,
GRAPHIC_CARD,
RAM_MODULE,
DISK,
DISC,
TAPE,
VHS,
DISKETTE,
CASE,
PSU,
MOTHERBOARD,
FAN,
CPU_COOLER,
GPU_COOLER,
NETWORK_CARD,
SOUND_CARD,
NETWORK_SWITCH,
WIFI_AP,
ROUTER,
MODEM,
MONITOR,
KEYBOARD,
MOUSE,
JOYSTICK,
HEADPHONES,
DAC,
MICROPHONE,
CAMERA,
PHONE,
LAPTOP,
COMPUTER,
SECURITY_KEY,
}
export enum FormFactorType {
M_ATX,
ATX,
E_ATX,
}
interface IItem {
type: ItemType;
name: string;
durability: number;
manufacturer?: Company | "Player";
availability?: number;
rarity?: number;
price?: number;
canFitInComputerCase?: boolean;
canFitInLaptopCase?: boolean;
canFitInMobileCase?: boolean;
}
interface IConnectedDevice extends IItem {
connector: ConnectorType;
}
interface IScrewdriver extends IItem {
quality: number;
}
interface ICPUCore {
originalClockSpeed: number;
clockSpeed: number;
threads: number;
cacheL1?: number;
cacheL2?: number;
}
interface ICPU extends IItem {
cores: ICPUCore[];
cacheL3?: number;
cacheL4?: number;
gpu?: IGPU;
npu?: INPU;
tdp: number;
process: number;
socket: SocketType;
}
interface IGPU extends IItem {
originalClockSpeed: number;
clockSpeed: number;
coreCount: number;
shadingUnitCount: number;
tmuCount: number;
ropCount: number;
tensorCoreCount: number;
rtCoreCount: number;
cacheL0?: number;
cacheL1?: number;
cacheL2?: number;
cacheL3?: number;
tops: number;
pixelRate: number;
textureRate: number;
fp16flops: number;
fp32flops: number;
fp64flops: number;
features: IGPUFeatures;
process: number;
}
interface INPU extends IItem {
tops: number;
}
interface IGPUFeatures {
directxVersion?: number;
openglVersion?: number;
openclVersion?: number;
vulkanVersion?: number;
cudaVersion?: number;
shaderModel?: number;
}
interface IGraphicsCard extends IConnectedDevice {
gpu: IGPU;
memory: IGraphicsCardMemory;
tdp: number;
}
interface IGraphicsCardMemory {
type: MemoryType;
originalClockSpeed: number;
clockSpeed: number;
busWidth: number;
bandwidth: number;
capacity: number;
}
interface IRAMModule extends IItem {
memoryType: MemoryType;
originalClockSpeed: number;
clockSpeed: number;
capacity: number;
tdp: number;
}
interface IDisk extends IConnectedDevice {
diskType: DiskType;
bandwidth: number;
capacity: number;
tdp: number;
storage: IStorage;
}
interface IDisc extends IItem {
discType: DiscType;
bandwidth: number;
capacity: number;
storage: IStorage;
}
interface ICase extends IItem {
formFactor: FormFactorType;
width: number;
height: number;
depth: number;
installedDevices: IItem[];
}
interface IPSU extends IItem {
formFactor: FormFactorType;
width: number;
height: number;
depth: number;
wattage: number;
connectors: ConnectorType[];
}
interface IMotherboard extends IItem {
formFactor: FormFactorType;
connectors: ConnectorType[];
socket: SocketType;
socketCount: number;
memoryType: MemoryType;
memorySlots: number;
installedCPUs: ICPU[];
installedRAMs: IRAMModule[];
installedDevices: IConnectedDevice[];
}
interface IModem extends IItem {
bandwidth: number;
net: INet;
}
export {
type IItem,
type IConnectedDevice,
type IScrewdriver,
type ICPU,
type IGPU,
type IGraphicsCard,
type IRAMModule,
type IDisk,
type IDisc,
type ICase,
type IPSU,
type IMotherboard,
type IModem,
};

4
src/state/location.ts Normal file
View file

@ -0,0 +1,4 @@
export enum Location {
PLAYER_HOME,
LOCAL_STORE,
}

51
src/state/memory.ts Normal file
View file

@ -0,0 +1,51 @@
export enum MemoryType {
DDR,
LPDDR,
LPDDRX,
DDR2,
LPDDR2,
LPDDR2X,
DDR3,
LPDDR3,
LPDDR3X,
DDR4,
LPDDR4,
LPDDR4X,
DDR5,
LPDDR5,
LPDDR5X,
DDR6,
LPDDR6,
LPDDR6X,
DDR7,
LPDDR7,
LPDDR7X,
DDR8,
LPDDR8,
LPDDR8X,
DDR9,
LPDDR9,
LPDDR9X,
GDDR1,
GDDR1X,
GDDR2,
GDDR2X,
GDDR3,
GDDR3X,
GDDR4,
GDDR4X,
GDDR5,
GDDR5X,
GDDR6,
GDDR6X,
GDDR7,
GDDR7X,
GDDR8,
GDDR8X,
GDDR9,
GDDR9X,
HBM,
HBM2,
HBM3,
HBM4,
}

4
src/state/motherboard.ts Normal file
View file

@ -0,0 +1,4 @@
export enum MotherboardFeatures {
BIOS,
UEFI,
}

11
src/state/software.ts Normal file
View file

@ -0,0 +1,11 @@
export enum SoftwareType {
OS,
}
export interface ISoftware {
type: SoftwareType;
name: string;
cpuUsage: number;
memoryUsage: number;
storageUsage: number;
}

49
src/state/state.ts Normal file
View file

@ -0,0 +1,49 @@
import { Location } from "./location.js";
import shops from "../data/shops.js";
import type { IGame } from "./types.js";
import cpus from "../data/items/cpus.js";
import rams from "../data/items/rams.js";
import psus from "../data/items/psus.js";
import cases from "../data/items/cases.js";
import motherboards from "../data/items/motherboards.js";
import other from "../data/items/other.js";
const game: IGame = {
state: {
time: 0,
player: {
name: "Aslan",
inventory: {
size: 2,
items: [],
},
location: Location.PLAYER_HOME,
},
car: {
inventory: {
size: 8,
items: [],
},
},
home: {
inventory: {
size: 100,
items: [
...cpus,
...rams,
...psus,
...motherboards,
...cases,
...other,
],
},
workbench: {
devices: [],
},
},
shops: shops,
},
};
export { game };
export default game.state;

57
src/state/storage.ts Normal file
View file

@ -0,0 +1,57 @@
import type { ISoftware } from "./software.js";
enum DiskType {
HDD,
SSD,
Flash,
}
enum DiscType {
LaserDisc,
CD,
DVD,
BluRay,
}
enum FilesystemType {
EXT,
EXT2,
EXT3,
EXT4,
FAT16,
FAT32,
NTFS,
EXFAT,
}
interface IStorage {
filesystem: IFileSystem;
}
interface IFileSystem {
type: FilesystemType;
rootDirectory: IDirectory;
}
interface IDirectory {
name: string;
directories: IDirectory[];
files: IFile[];
}
interface IFile {
name: string;
size: string;
isSoftware: boolean;
contents: string | ISoftware;
}
export {
DiskType,
DiscType,
FilesystemType,
type IStorage,
type IFileSystem,
type IDirectory,
type IFile,
};

68
src/state/types.ts Normal file
View file

@ -0,0 +1,68 @@
import type { IItem, IModem } from "./item.js";
import type { Location } from "./location.js";
interface IGame {
state: IState;
}
interface IState {
time: number;
player: IPlayer;
car: ICar;
home: IHome;
shops: IShop[];
}
interface IPlayer {
name: string;
inventory: IInventory;
location: Location;
}
interface ICar {
inventory: IInventory;
}
interface IHome {
inventory: IInventory;
workbench: IWorkbench;
modem?: IModem;
}
interface IInventory {
size: number;
items: IItem[];
}
interface IWorkbench {
devices: IItem[];
}
interface IWebsite {
name: string;
ip: string;
domain: string;
html: string;
}
interface INet {
ip?: string;
}
interface IShop {
name: string;
items: IItem[];
}
export {
type IGame,
type IState,
type IPlayer,
type ICar,
type IHome,
type IInventory,
type IWorkbench,
type IWebsite,
type INet,
type IShop,
};

46
tsconfig.json Normal file
View file

@ -0,0 +1,46 @@
{
// Visit https://aka.ms/tsconfig to read more about this file
"compilerOptions": {
// File Layout
"rootDir": "./src",
"outDir": "./dist",
// Environment Settings
// See also https://aka.ms/tsconfig/module
"module": "nodenext",
"target": "esnext",
"types": [],
// For nodejs:
// "lib": ["esnext"],
// "types": ["node"],
// and npm install -D @types/node
// Other Outputs
"sourceMap": true,
"declaration": true,
"declarationMap": true,
// Stricter Typechecking Options
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
// Style Options
// "noImplicitReturns": true,
// "noImplicitOverride": true,
// "noUnusedLocals": true,
// "noUnusedParameters": true,
// "noFallthroughCasesInSwitch": true,
// "noPropertyAccessFromIndexSignature": true,
// Recommended Options
"strict": true,
"jsx": "react-jsx",
"verbatimModuleSyntax": true,
"isolatedModules": true,
"noUncheckedSideEffectImports": true,
"moduleDetection": "force",
"skipLibCheck": true,
"resolveJsonModule": true,
"esModuleInterop": true
}
}