f1e915c379
Update the launcher design reference so active downloads show how many LAN peers are currently seeding the transfer. The reference now places the peer chip between speed and ETA, describes the singular/plural copy, and records how the ETA and peer count collapse in narrow modal layouts. Test Plan: - git diff --cached --check
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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',
|
||
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;
|