91c709960a
Document the profile settings added to the launcher design and the new Start Server detail action. The settings contract now includes a persisted username and language choice, and the game detail overlay shows Start Server only for installed games that can host a dedicated server. The reference mock now includes the matching Profile controls, a server icon, server-capable sample catalog entries, and the updated detail/settings artboards so implementation can follow the selected design direction. Test Plan: - git diff --cached --check Refs: design/README.md
217 lines
12 KiB
React
217 lines
12 KiB
React
// data.jsx — game catalog for the SoftLAN launcher mock
|
||
// Each game has: id, title, size (GB), version (date), description, state, players (min-max), tags, cover (color pair + optional accent shape)
|
||
// state: 'installed' | 'local' | 'none' (local = downloaded but not installed yet)
|
||
|
||
const GAMES = [
|
||
{
|
||
id: '8bitarmies', title: '8-Bit Armies', size: 1.9, version: '2016.10.24',
|
||
desc: "A fast-paced retro-styled RTS with bright voxel armies, three factions, and zero patience for slow players. Tank-rush, build queues, and a campaign that doesn't waste your time.",
|
||
state: 'installed', players: '1–8', tags: ['RTS', 'Multiplayer', 'LAN'],
|
||
cover: { c1: '#f59e0b', c2: '#b91c1c', accent: '#fde047', mood: 'arcade' },
|
||
},
|
||
{
|
||
id: 'aoe2hd', title: 'Age of Empires II (HD)', size: 8.6, version: '2018.01.31',
|
||
desc: "The HD remaster of the strategy classic. Lead one of thirteen civilizations from the dark ages through the imperial age, and finally settle who actually deserved that wonder.",
|
||
state: 'local', players: '1–8', tags: ['RTS', 'Historical', 'LAN'],
|
||
cover: { c1: '#7c2d12', c2: '#1c1917', accent: '#fbbf24', mood: 'gothic' },
|
||
},
|
||
{
|
||
id: 'avp', title: 'Aliens vs. Predator', size: 35.0, version: '2019.10.01',
|
||
desc: "Three campaigns, three nightmares. Be the alien stalking the dark, the predator hunting both, or the marine just trying to make it home with a working flashlight.",
|
||
state: 'downloading', progress: 0.32, speed: 49.4, peers: 5, players: '2–16', tags: ['FPS', 'Horror', 'Multiplayer'],
|
||
cover: { c1: '#064e3b', c2: '#020617', accent: '#34d399', mood: 'dark' },
|
||
},
|
||
{
|
||
id: 'amongus', title: 'Among Us', size: 0.3, version: '2021.11.05',
|
||
desc: "Crewmates fix the ship. Impostors sabotage it and vent through walls. Friendships are tested. The orange one is always sus.",
|
||
state: 'installed', players: '4–15', tags: ['Social Deduction', 'Casual'],
|
||
cover: { c1: '#ef4444', c2: '#1e3a8a', accent: '#fef08a', mood: 'playful' },
|
||
},
|
||
{
|
||
id: 'bf1942', title: 'Battlefield 1942', size: 7.8, version: '2016.01.30', canHostServer: true,
|
||
desc: "The original Battlefield. WWII on land, sea, and air across 16 maps. The mod scene basically reinvented PC gaming on top of this engine.",
|
||
state: 'installed', players: '2–64', tags: ['FPS', 'Vehicles', 'LAN'],
|
||
cover: { c1: '#92400e', c2: '#1c1917', accent: '#facc15', mood: 'war' },
|
||
},
|
||
{
|
||
id: 'bf2', title: 'Battlefield 2 Complete', size: 8.0, version: '2021.12.27', canHostServer: true,
|
||
desc: "Modern combat with commander mode, squads, and the kind of jet-vs-jet duels you tell stories about for a decade.",
|
||
state: 'local', players: '2–64', tags: ['FPS', 'Vehicles', 'Tactical'],
|
||
cover: { c1: '#3f3f46', c2: '#0a0a0a', accent: '#22d3ee', mood: 'tactical' },
|
||
},
|
||
{
|
||
id: 'blazerush', title: 'BlazeRush', size: 1.3, version: '2021.12.27',
|
||
desc: "Top-down arcade racing with no fuel, no health bar, and absolutely no brakes. Ram, boost, win.",
|
||
state: 'none', players: '1–8', tags: ['Racing', 'Arcade'],
|
||
cover: { c1: '#f97316', c2: '#7c2d12', accent: '#fde047', mood: 'arcade' },
|
||
},
|
||
{
|
||
id: 'cod2', title: 'Call of Duty 2', size: 7.0, version: '2016.09.22', canHostServer: true,
|
||
desc: "WWII shooter — Russian, British and American campaigns, plus the multiplayer that defined LAN parties for years.",
|
||
state: 'installed', players: '2–32', tags: ['FPS', 'War'],
|
||
cover: { c1: '#57534e', c2: '#1c1917', accent: '#fbbf24', mood: 'war' },
|
||
},
|
||
{
|
||
id: 'cod4mw', title: 'Call of Duty 4: Modern Warfare', size: 13.0, version: '2016.09.21', canHostServer: true,
|
||
desc: "The shooter that flipped the genre to modern combat and minted a generation of esports careers. All Ghillied Up still holds up.",
|
||
state: 'local', players: '2–32', tags: ['FPS', 'Modern'],
|
||
cover: { c1: '#525252', c2: '#0a0a0a', accent: '#84cc16', mood: 'tactical' },
|
||
},
|
||
{
|
||
id: 'coduo', title: 'Call of Duty: United Offensive', size: 3.8, version: '2018.09.08', canHostServer: true,
|
||
desc: "Expansion to the original CoD. Battle of the Bulge, Sicily, Kursk. Adds tanks, B-17 sequences, and the flamethrower nobody asked for but everybody loved.",
|
||
state: 'none', players: '2–32', tags: ['FPS', 'Expansion'],
|
||
cover: { c1: '#78716c', c2: '#292524', accent: '#fb923c', mood: 'war' },
|
||
},
|
||
{
|
||
id: 'ra3', title: 'C&C: Red Alert 3', size: 8.2, version: '2018.04.12',
|
||
desc: "Cold War alt-history RTS. Soviets, Allies, and the Empire of the Rising Sun — every cutscene live-action and absolutely deranged.",
|
||
state: 'installed', players: '1–6', tags: ['RTS', 'Co-op'],
|
||
cover: { c1: '#991b1b', c2: '#450a0a', accent: '#fde047', mood: 'propaganda' },
|
||
},
|
||
{
|
||
id: 'cncgen', title: 'C&C Generals: Zero Hour', size: 2.1, version: '2017.11.15',
|
||
desc: "Modern-warfare RTS expansion with generals challenges. USA, China, GLA — pick your asymmetry and rush something.",
|
||
state: 'local', players: '1–8', tags: ['RTS', 'Modern'],
|
||
cover: { c1: '#a16207', c2: '#422006', accent: '#facc15', mood: 'war' },
|
||
},
|
||
{
|
||
id: 'cs', title: 'Counter-Strike 1.6', size: 0.7, version: '2014.01.21', canHostServer: true,
|
||
desc: "The 1.6 build still everyone insists was the peak. Terrorists vs Counter-Terrorists, AWP camping, de_dust2.",
|
||
state: 'installed', players: '2–32', tags: ['FPS', 'Competitive', 'LAN'],
|
||
cover: { c1: '#1e40af', c2: '#0c1f3a', accent: '#fbbf24', mood: 'tactical' },
|
||
},
|
||
{
|
||
id: 'css', title: 'Counter-Strike: Source', size: 4.3, version: '2014.10.23', canHostServer: true,
|
||
desc: "CS reborn on the Source engine. Same maps, same rules, with physics that lets the molotovs work properly.",
|
||
state: 'installed', players: '2–32', tags: ['FPS', 'Competitive'],
|
||
cover: { c1: '#1d4ed8', c2: '#0c1f3a', accent: '#f59e0b', mood: 'tactical' },
|
||
},
|
||
{
|
||
id: 'cube2', title: 'Cube 2: Sauerbraten', size: 0.4, version: '2013.09.20', canHostServer: true,
|
||
desc: "Open-source arena FPS with in-game level editing. Fast, free, and one of those things every LAN party always had a copy of.",
|
||
state: 'none', players: '2–16', tags: ['FPS', 'Open Source'],
|
||
cover: { c1: '#dc2626', c2: '#7f1d1d', accent: '#f1f5f9', mood: 'arcade' },
|
||
},
|
||
{
|
||
id: 'doom3', title: 'Doom 3', size: 2.2, version: '2012.01.31', canHostServer: true,
|
||
desc: "Sci-fi horror reboot of the franchise. Mars Research Facility, demonic incursion, the shotgun that started a flashlight debate.",
|
||
state: 'local', players: '2–16', tags: ['FPS', 'Horror'],
|
||
cover: { c1: '#7f1d1d', c2: '#000000', accent: '#f97316', mood: 'dark' },
|
||
},
|
||
{
|
||
id: 'l4d2', title: 'Left 4 Dead 2', size: 6.5, version: '2020.08.15', canHostServer: true,
|
||
desc: "Co-op zombie survival with the AI Director rewriting every campaign run. Bring four friends or four strangers; the chainsaw works the same.",
|
||
state: 'installed', players: '1–8', tags: ['Co-op', 'FPS', 'Horror'],
|
||
cover: { c1: '#15803d', c2: '#052e16', accent: '#fef08a', mood: 'horror' },
|
||
},
|
||
{
|
||
id: 'minecraft', title: 'Minecraft', size: 1.0, version: '2024.03.01', canHostServer: true,
|
||
desc: "Infinite voxel sandbox. Build, mine, survive, get blown up by a creeper. The LAN button is right there.",
|
||
state: 'installed', players: '2–100', tags: ['Sandbox', 'Survival', 'LAN'],
|
||
cover: { c1: '#15803d', c2: '#7c2d12', accent: '#fde68a', mood: 'sandbox' },
|
||
},
|
||
{
|
||
id: 'portal2', title: 'Portal 2', size: 11.0, version: '2014.01.01',
|
||
desc: "Puzzle-shooter sequel with a full co-op campaign — two players, two portals each, infinite ways to get GLaDOS to insult you.",
|
||
state: 'local', players: '1–2', tags: ['Puzzle', 'Co-op'],
|
||
cover: { c1: '#ea580c', c2: '#1e293b', accent: '#22d3ee', mood: 'tech' },
|
||
},
|
||
{
|
||
id: 'quake3', title: 'Quake III Arena', size: 0.5, version: '2010.08.15', canHostServer: true,
|
||
desc: "Arena FPS in its most distilled form. Rocket jumps, rail-gun duels, and a netcode that's still the benchmark.",
|
||
state: 'downloading', progress: 0.71, speed: 12.8, peers: 3, players: '2–16', tags: ['FPS', 'Arena', 'LAN'],
|
||
cover: { c1: '#7f1d1d', c2: '#0a0a0a', accent: '#fbbf24', mood: 'dark' },
|
||
},
|
||
{
|
||
id: 'starcraft', title: 'StarCraft: Brood War', size: 1.2, version: '2018.04.16',
|
||
desc: "Sci-fi RTS — Terran, Zerg, Protoss. Still played at the highest level decades later for a reason.",
|
||
state: 'installed', players: '1–8', tags: ['RTS', 'Sci-Fi'],
|
||
cover: { c1: '#1e3a8a', c2: '#172554', accent: '#22d3ee', mood: 'scifi' },
|
||
},
|
||
{
|
||
id: 'tf2', title: 'Team Fortress 2', size: 22.0, version: '2023.06.18', canHostServer: true,
|
||
desc: "Class-based shooter with nine archetypes, absurd hats, and a meta with more history than most actual sports.",
|
||
state: 'local', players: '2–32', tags: ['FPS', 'Class-based'],
|
||
cover: { c1: '#b45309', c2: '#7c2d12', accent: '#fbbf24', mood: 'cartoon' },
|
||
},
|
||
{
|
||
id: 'ut2k4', title: 'Unreal Tournament 2004', size: 5.2, version: '2012.06.01', canHostServer: true,
|
||
desc: "Arena shooter at maximum velocity. Onslaught, Assault, Bombing Run — vehicles, jump boots, the announcer screaming HEADSHOT.",
|
||
state: 'none', players: '2–32', tags: ['FPS', 'Arena'],
|
||
cover: { c1: '#854d0e', c2: '#422006', accent: '#fde047', mood: 'arena' },
|
||
},
|
||
{
|
||
id: 'warcraft3', title: 'Warcraft III: TFT', size: 1.3, version: '2018.03.25',
|
||
desc: "Hero-driven RTS whose custom-game scene birthed Dota, tower defense, and at least three other genres that ate the industry.",
|
||
state: 'installed', players: '1–12', tags: ['RTS', 'Fantasy'],
|
||
cover: { c1: '#a16207', c2: '#422006', accent: '#fbbf24', mood: 'fantasy' },
|
||
},
|
||
];
|
||
|
||
// Helpers
|
||
const fmtSize = (gb) => gb < 1 ? `${Math.round(gb * 1024)} MB` : `${gb.toFixed(1)} GB`;
|
||
const STATE_META = {
|
||
installed: { label: 'Installed', dot: '#22c55e' },
|
||
local: { label: 'Local', dot: '#f59e0b' },
|
||
downloading: { label: 'Downloading', dot: 'var(--accent)' },
|
||
none: { label: '', dot: 'transparent' },
|
||
};
|
||
const ACTION_FOR_STATE = {
|
||
installed: { label: 'Play', kind: 'play' },
|
||
local: { label: 'Install', kind: 'install' },
|
||
downloading: { label: 'Downloading', kind: 'downloading' },
|
||
none: { label: 'Download', kind: 'download' },
|
||
};
|
||
|
||
// Format helpers for download UI
|
||
const fmtSpeed = (mbps) => mbps >= 100 ? `${Math.round(mbps)} MB/s` : `${mbps.toFixed(1)} MB/s`;
|
||
const fmtSpeedShort = (mbps) => `${Math.round(mbps)} MB/s`;
|
||
const fmtBytes = (gb) => {
|
||
if (gb < 1) return `${Math.round(gb * 1024)} MB`;
|
||
// No trailing zeros: 35 GB, 11.4 GB, 2.35 GB
|
||
if (gb >= 10) return `${gb.toFixed(1).replace(/\.0$/,'')} GB`;
|
||
return `${gb.toFixed(2).replace(/0$/,'').replace(/\.$/,'')} GB`;
|
||
};
|
||
const fmtEta = (sec) => {
|
||
if (!isFinite(sec) || sec <= 0) return '—';
|
||
if (sec < 60) return `${Math.round(sec)} s`;
|
||
const m = Math.round(sec / 60);
|
||
if (m < 60) return `${m} min`;
|
||
return `${Math.floor(m/60)} h ${m%60} min`;
|
||
};
|
||
|
||
const isLocalish = (s) => s === 'installed' || s === 'local' || s === 'downloading';
|
||
const countByFilter = (games) => ({
|
||
all: games.length,
|
||
local: games.filter(g => isLocalish(g.state)).length,
|
||
installed: games.filter(g => g.state === 'installed').length,
|
||
});
|
||
|
||
const filterGames = (games, key) => {
|
||
if (key === 'all') return games;
|
||
if (key === 'local') return games.filter(g => isLocalish(g.state));
|
||
if (key === 'installed') return games.filter(g => g.state === 'installed');
|
||
return games;
|
||
};
|
||
|
||
// Storage figures (mock)
|
||
const STORAGE = {
|
||
installed: 78.4, // GB
|
||
local: 41.2,
|
||
free: 384.1,
|
||
total: 512,
|
||
};
|
||
|
||
window.GAMES = GAMES;
|
||
window.STATE_META = STATE_META;
|
||
window.ACTION_FOR_STATE = ACTION_FOR_STATE;
|
||
window.countByFilter = countByFilter;
|
||
window.filterGames = filterGames;
|
||
window.fmtSize = fmtSize;
|
||
window.fmtSpeed = fmtSpeed;
|
||
window.fmtSpeedShort = fmtSpeedShort;
|
||
window.fmtBytes = fmtBytes;
|
||
window.fmtEta = fmtEta;
|
||
window.STORAGE = STORAGE;
|