Plán multiplayeru: každý proti každému pro 2–8 hráčů

Stav: návrh implementace, 30. 10. 2026. Tento dokument popisuje budoucí změny; multiplayer ani jeho nasazení zatím neprovádí.

1. Cíl a hranice

Do hlavního menu přidat dvě možnosti: Singleplayer a Multiplayer. Singleplayer zachová současnou kampaň, pravidla, ovládání, grafiku, mobilní vyvážení a offline PWA. Multiplayer bude samostatný online režim každý proti každému, ve kterém se 2–8 lidských hráčů pohybuje po společné mapě, bojuje mezi sebou a současně potkává počítačové nepřátele.

Hráč založí místnost, ostatní se připojí přes seznam her nebo pozvánku. Každý si před zápasem vybere obličej. Přezdívky ani přihlášení nebudou potřeba. Počítačoví nepřátelé budou mít jeden společný vzhled s kuklou zakrývající tvář; jejich různé zbraně a bojové profily zůstanou zachované.

Doporučené řešení: ponechat Vite, TypeScript a současný Canvas 2D raycaster; přidat autoritativní Node.js server s Express a Socket.IO podle projektu krysi-jmena. Převzít také způsob nasazení přes SSH/SCP, Docker Compose, Nginx a verzované releasy s rollbackem.

2. Z čeho plán vychází

Současná hra BUNKER 07

Oblast

Zjištění a dopad na návrh

Spouštění

src/main.ts vytváří jednu instanci Game; doplnit výběr režimu a samostatný multiplayerový klient.

Herní smyčka

src/game/Game.ts spojuje lokální simulaci s ovládáním, zvukem a UI. Celou třídu nelze jednoduše spustit na serveru.

AI

updateEnemies v src/game/enemies.ts přijímá jednoho hráče a vrací součet poškození. Pro více cílů potřebuje výběr cíle a adresné události poškození.

Boj

combat.ts, playerCombat.ts, enemyAim.ts, grenades.ts, weapons.ts a inventory.ts obsahují základ znovupoužitelných pravidel. Typy a některá pravidla dnes rozlišují přímo hráče a nepřítele.

Mapa

src/levels/campaign.ts vytváří tři mapy 54 × 54 pro postup od startu k bossovi a východu. Rozložení je určené kampani.

Prostředí

world.ts, collision.ts a levels/dynamics.ts řeší průchodnost, výhled, cesty a bedny. Tyto principy použít také v aréně.

Postavy

enemyCatalog.ts obsahuje deset vzhledů včetně bosse, šest aktivních běžných postav a tři vypnuté běžné varianty. Pro osm hráčských portrétů lze vybrat i z archivovaných variant.

Grafika

assets/manifest.ts a atlasové build skripty načítají animace postav. Vzhled je nyní v katalogu svázaný se zbraní, což multiplayer musí oddělit.

Mobil

difficulty.ts snižuje příchozí poškození od AI na dotykovém zařízení. V jednom společném zápase musí server použít jednotná pravidla pro všechny.

Provoz

Dnešní npm run deploy publikuje statický dist/ do /www/bunker07/; Nginx obsluhuje https://bunker07.rozd.cz/. Backend zatím chybí.



Zdrojem pravdy pro přebírané parametry bude aktuální kód při implementaci. Některé starší dokumenty popisují dřívější vyvážení; nepřepisovat podle nich současné hodnoty.

Referenční projekt krysi-jmena

Prohlédnutý projekt: C:/Users/roman/OneDrive/DEV/vibecoding/krysi-jmena. Samotná aplikace je v jeho podsložce krysi-jmena/.

Co převzít

Referenční soubory relativně ke kořeni projektu krysi-jmena

Node.js 24, Express 5, Socket.IO 4

krysi-jmena/package.json, krysi-jmena/server/index.js

Registr místností, kapacita, hostitel, úklid

krysi-jmena/server/rooms.js

Anonymní identita a obnovení tokenem

krysi-jmena/server/sessions.js

Ověřování akcí, potvrzení, deduplikace a limity

krysi-jmena/server/handlers.js, krysi-jmena/server/client-ip.js

Připojování a návrat po výpadku

krysi-jmena/public/js/connection.js, krysi-jmena/public/js/store.js

Lobby a sdílení pozvánky

krysi-jmena/public/js/views/lobby.js, krysi-jmena/public/js/room-invite.js

Kontejner a provozní omezení

krysi-jmena/Dockerfile, krysi-jmena/compose.yaml

Windows deploy, release a ověření

deploy/deploy.ps1, deploy/verify.mjs, krysi-jmena/deploy/release.sh

Nginx, záloha a rollback

krysi-jmena/deploy/nginx-rat.conf, krysi-jmena/deploy/configure-nginx.py, deploy/README.md



Převzít infrastrukturu a ověřené postupy. Pravidla týmů, rolí, tahů a karet nahradit pravidly FPS. Referenční limit deseti akcí za sekundu a posílání celého stavu po každé akci se pro pohyb FPS nehodí; rozdělit řídicí zprávy a průběžné vstupy.

3. Navržená pravidla první verze

Následující hodnoty jsou doporučené výchozí nastavení, protože zadání neurčuje délku zápasu, skórování ani respawn. Soustředit je do samostatné multiplayerové konfigurace pro pozdější ladění.

Pravidlo

Návrh

Režim

Deathmatch, každý proti každému; žádné týmy.

Lidé

Start s 2–8 připojenými hráči; kapacita místnosti nastavitelná od 2 do 8. AI nezabírá lidské sloty.

Začátek

Odpočet 5 sekund po načtení mapy a grafiky všemi účastníky.

Výbava

100 zdraví, bez armoru, Luger s 32 náboji a dostupné pěsti. Pistole je vybraná. Stejné při každém respawnu.

Umístění

Server náhodně přiřadí bezpečná místa v okrajových sektorech mapy. Hráči se nespawnují vedle sebe.

Konec

20 zabití lidských soupeřů nebo 10 minut hry, podle toho, co nastane dřív.

Skóre

Zabití člověka +1 frag. AI má samostatné počítadlo a do vítězného limitu se nepočítá. Sebevražda −1 frag; smrt od AI bez fragu pro jiného hráče.

Shoda výsledků

Vyhrává nejvyšší počet fragů, při shodě nižší počet úmrtí; při další shodě sdílené vítězství. Výsledky jednoho serverového kroku vyhodnotit společně.

Smrt

Krátká obrazovka smrti, automatický respawn za 3 sekundy. Zahodit právě drženou palnou zbraň se zbývající municí; pistoli ani pěsti jako kořist nevytvářet.

Ochrana po respawnu

Nejvýše 2 sekundy, viditelná a končí prvním útokem hráče; stejně vůči lidem i AI.

Výzbroj

Další zbraně z mrtvol AI a hráčů, munice a lékárničky na mapě. Sbírání, limity a obnovu zásob řídí server.

AI

Stejné běžné bojové profily jako v singleplayeru, společný vzhled s kuklou. První aréna bez kampaňového bosse a zamčeného východu.

PC a mobil

Společné serverové hodnoty poškození a rychlostí; zachovat dotykové ovládání. Mobilní snížení poškození nadále platí v singleplayeru.

Pozdní připojení

Noví hráči pouze do lobby. Během zápasu povolit jen návrat již přihlášeného účastníka.

Pauza

Menu zastaví vstupy daného hráče, společný zápas pokračuje a jeho postava zůstává zranitelná.



Po výbuchu nebo dohoření ohně připsat zabití původnímu vlastníkovi útoku, i když už zemřel. Každou smrt vyhodnotit právě jednou. Lidé mohou zraňovat všechny ostatní lidi i AI, AI útočí na lidi; vlastní výbušniny a oheň zraňují také vlastníka. AI se v první verzi navzájem nepoškozuje. Exploze, oheň a průstřely respektují zdi i bedny.

Poškození proti lidem definovat explicitně v multiplayerové konfiguraci. Jako výchozí použít parametry hráčských palných zbraní; pro pěsti navrhnout 25 poškození proti člověku. Kampaňové škálování pěsti podle maximálního zdraví nepřítele nesmí automaticky znamenat dvě rány na lidského soupeře. Pravidla granátů, armoru a ohně musí mít samostatně otestované lidské cíle. Hodnoty kampaně tím neměnit.

4. Průchod lobby a výběr obličeje

  1. Hlavní menu nabídne Singleplayer a Multiplayer. Síťový klient načítat až při vstupu do multiplayeru.

  2. Multiplayer zobrazí dostupné místnosti: název nebo automatický kód hry, počet lidí, kapacitu a stav. Hráči nepotřebují zadávat jméno.

  3. Vytvořit hru založí lobby. Hostitel vybere kapacitu 2–8 a obličej; základní pravidla jsou předvyplněná. Ostatní se připojí ze seznamu nebo odkazem ?room=<roomId>.

  4. Každý má kartu s portrétem, indikátorem připojení, stavem připravenosti a případně označením hostitele. Vlastní karta má štítek TY.

  5. V místnosti musí být každý obličej unikátní. Výběr atomicky rezervuje server; při souběžném výběru stejné tváře uspěje jen jeden hráč.

  6. Hráč potvrdí Připraven. Změna obličeje nebo pravidel připravenost dotčených hráčů zruší. Hostitel spustí zápas, pokud jsou alespoň dva lidé a všichni mají obličej a připravenost.

  7. Server uzavře vstupy do místnosti, pošle inicializaci zápasu a čeká na match:loaded. Po potvrzení všech spustí odpočet a společný čas zápasu. Při nenačtení do 30 sekund vrátí místnost do lobby s vysvětlením.

  8. Po zápase zobrazit výsledky s portréty: fragy, úmrtí a zvlášť zabití AI. Návrat do lobby zachová místnost i obličeje, zruší připravenost a umožní odvetu.

Identita bude interní playerId a tajný obnovovací token jako v referenční hře. avatarId je pouze vzhled, neslouží k autorizaci. Portréty použít také v tabulce skóre a v hláškách o zabití. Pro čtečky obrazovky dát tvářím krátké rozlišovací popisky bez požadavku na osobní jméno.

Připravit nejméně osm jasně rozlišitelných obličejů. Vybrat osm z existujících běžných a archivovaných portrétů; případné nové tváře doplnit až po kontrole čitelnosti. Nepovolovat kvůli tomu vypnuté postavy v kampani. Katalog multiplayerových avatarů bude samostatný. Portrét nemění zdraví, rychlost, zbraň ani velikost zásahové oblasti.

5. Mapa a rozmístění

Rozhodnutí: samostatná aréna

Současnou mapu lze využít pro první technický test propojení dvou klientů. Pro výsledný režim doporučuji novou ručně navrženou arénu: kampaně mají jeden start, postupovou trasu, zásoby v odbočkách a závěr s bossem. Pro férové opakované střety 2–8 lidí vyžadují jiné rozložení.

První mapa Aréna 01 – skladový okruh, výchozí půdorys přibližně 40 × 40 polí:

Generátor nemusí vytvářet úplně nový labyrint při každém zápase. První verze použije stabilní geometrii a serverové losování startů, AI a vybraných zásob. Pozdější varianty mohou používat seed, vždy po validaci průchodnosti.

Férový spawn

Server vytvoří pořadí vhodných bodů a zvolí kandidáta mimo zeď, bednu, tělo a aktivní oheň, bez přímého výhledu blízkého soupeře či AI a s co největší vzdáleností po průchozí trase od hrozeb. Jako výchozí cíl zkusit alespoň 6 polí po trase, hodnotu ověřit pro osm hráčů. Úvodní starty rozdělit mezi vzdálené okrajové sektory.

Pokud není ideální bod, použít bezpečný průchozí bod s nejlepším hodnocením a krátkou ochranou; nikdy nevytvářet postavu ve zdi. Před spuštěním ověřit dosažitelnost všech sektorů, zásob i tras a znovu ji zkontrolovat po rozmístění beden.

Server pošle hotovou mřížku, umístění objektů, mapId, mapVersion, seed a hash mapy. Samotný seed nestačí: klient nesmí vlastní odlišnou verzí generátoru vytvořit jinou mapu. Náhodná rozhodnutí a výsledné rozmístění určuje server.

6. AI s jednotnou kuklou

Oddělit bojový profil od vzhledu. Všechny multiplayerové stráže budou mít skinId: masked-guard, ale zachovají své aiProfileId, zbraň, zdraví, kadenci, dávky, reakce, míření, odvetu po zásahu a rychlosti podle aktuálního singleplayerového kódu. Zachovat také hlídky, reakci na zvuk, pronásledování, obcházení krytu a šanci na krátký výpad.

Nejde o sloučení všech nepřátel do jednoho bojového typu: AK, Uzi, Tommy Gun, FG 42, Mosin a těžký kulomet se dál chovají podle vlastních profilů. Kořist a případné nápoje určit profilem, nikoli obrázkem kukly. Stejný vzhled nesmí omylem sjednotit jejich parametry ani jim přidělit všem jednu zbraň.

Změna AI pro více hráčů

Výchozí počty AI k ověření: 6 pro dva lidi, 10 pro 3–4 a 12 pro 5–8. Počet zafixovat na začátku zápasu. Mrtvé stráže obnovovat po přibližně 15 sekundách v bezpečné oblasti, mimo bezprostřední výhled lidí. Omezit počet mrtvol a kořisti i jejich životnost, aby dlouhý zápas neplnil paměť.

Grafické podklady pro pozdější implementaci

Vytvořit nový společný model stráže s tmavou kuklou: skrytá tvář, zachované oči, čitelná silueta a jednotné oblečení. Použít stávající styl a nativní snímky 192 × 256 s totožným ukotvením nohou. Připravit animace idle, walk, attack, hurt, death a varianty držených zbraní. Kukla musí být součástí všech potřebných snímků a směrů.

Pro lidi zajistit čitelné rozlišení zepředu, z boku i zezadu a zobrazení aktuálně držené zbraně. Existující převážně čelní atlasy nepovažovat automaticky za hotové multiplayerové postavy. Využít podporu směrových manifestů a při implementaci připravit například osm směrů nebo odpovídající skládání vrstev těla, hlavy a zbraně. Zásahová oblast zůstane stejná pro všechny lidské avatary.

Nové atlasy načítat jen pro multiplayer. Stávající katalog i grafika nepřátel singleplayeru zůstanou zachované. Samotné generování a zapojení obrázků je implementační úkol, nikoli výstup tohoto plánu.

7. Architektura a rozdělení odpovědnosti

Prohlížeč: Vite + TypeScript + Canvas raycaster
├─ Singleplayer → současný Game, místní simulace, offline PWA
└─ Multiplayer → lobby, vstupy, predikce, vykreslení serverového stavu
│ HTTPS + Socket.IO / WSS
Nginx: bunker07.rozd.cz │
├─ statická hra │
└─ /socket.io/, /health, /api/*
▼
Docker Compose → Node.js 24 + Express 5 + Socket.IO 4
├─ místnosti, tokeny, hostitel, limity
└─ každá aktivní místnost: mapa, lidé, AI, boj, zásoby, skóre

Backend drží skutečnou pozici, zdraví, inventář, časovače zbraní, AI, projektily, zásahy, kořist, respawny a výsledky. Klient posílá ovládání a požadavky. Neposílá rozhodnutí „zasáhl jsem“, „mám tuto pozici“ nebo „přidej mi zdraví“.

Jeden proces obslouží více oddělených místností. Každá má vlastní svět, čas, generátor náhody a životní cyklus; síťový kanál musí ověřovat členství. První verze bude bez databáze, Redis, účtů a P2P. Restart procesu ukončí rozehrané zápasy a zneplatní obnovovací tokeny, stejně jako v referenční hře. Kapacitu serveru nastavit až podle měření FPS simulace; nepřebírat automaticky limit 100 místností z tahové hry.

Sdílené jádro

Vyčlenit čisté funkce a datové typy pro pohyb, kolize, zbraně, inventář, zásahy a AI. Nesmí importovat DOM, Canvas, audio, Image, virtuální Vite moduly ani prohlížečové načítání atlasů. Na serveru běží bez grafiky. Seedovaný generátor a čas předávat jako závislosti, nespoléhat na samostatné klientské Math.random().

Kampaň ponechat na současné smyčce Game. Změny sdílených pravidel dělat po malých krocích a ověřovat stávajícími testy. Kolem AI ponechat kompatibilní vstup pro jednoho hráče, který používá společnou logiku jednoho kroku. Multiplayer dostane samostatný řadič, ne síťové podmínky rozeseté do celé kampaně.

8. Síťový protokol a plynulost

Frekvence a doručování

Vrstva

Výchozí návrh

Serverová simulace

Pevný krok 1/60 s, blízký současné simulaci. Limitovat dohánění zpoždění a měřit délku kroků.

Vstupy klienta

Přibližně 30 zpráv/s; obsahují pořadové číslo, normalizovaný pohyb, směr pohledu, stav útoku a požadovanou zbraň.

Stav světa

Přibližně 20 snímků/s, každý s matchId, serverovým krokem, časem a potvrzením zpracovaných vstupů.

Vykreslování

Nezávisle přes requestAnimationFrame, cílově 60 FPS na PC a alespoň 30 FPS na cílovém mobilu.

Lobby a příkazy

Potvrzované požadavky s requestId, chybovým kódem a deduplikací jako v krysi-jmena.



Průběžný stav lze odesílat přes volatile a zahodit staré čekající snímky; další úplný snímek opraví stav. Začít kompaktními úplnými snímky, rozdílové zprávy přidat až při prokázané potřebě. Posílat pouze potřebná data, nikdy tokeny jiných lidí ani interní struktury AI.

Pohyb lokálního hráče predikovat stejnou funkcí jako na serveru. Server potvrdí poslední zpracovaný vstup, klient opraví pozici a přehraje zbývající vstupy. Pohyb ostatních postav interpolovat s výchozím zpožděním přibližně 100 ms. Míření a lokální zvuk výstřelu reagují ihned, zásah a změnu zdraví potvrzuje server. Události zvuků a efektů opatřit ID proti dvojímu přehrání.

Vstup není klientem určená délka simulace. Server zpracuje konečný stav ovládání jen v mezích vlastního času; záplava zpráv nezrychlí pohyb. Jednorázové interakce a hrany stisku/uvolnění mají vlastní sekvenci a potvrzení, případně se opakují do potvrzení. To je nutné zejména pro hod granátu a Molotova: ztracené uvolnění nesmí nechat přípravu viset. Staré zprávy z jiného zápasu nebo života (lifeId) odmítnout.

Pro hratelnou střelbu při běžném pingu naplánovat omezenou kompenzaci zpoždění palných zbraní: uchovávat historii pozic přibližně 200 ms, ověřovat klientský čas proti odhadu serveru a započítat interpolační zpoždění. Při ověření výstřelu přepočítat postavy k příslušnému okamžiku, ale nevracet celý svět, zdraví nebo zásoby. Nepřijmout zásah předchozího života a nekompenzovat čas mimo povolené okno. Granáty a oheň simulovat v aktuálním serverovém čase.

Socket.IO standardně neposkytuje zaručené opětovné doručení každé zprávy po výpadku. Deduplikace, potvrzení důležitých akcí a úplná synchronizace jsou součástí aplikace; její správnost nesmí záviset pouze na automatickém reconnectu. Viz doručování zpráv a obnova spojení.

Navržené zprávy

Směr

Zprávy a účel

Klient → server, lobby

rooms:subscribe, room:create, room:join, room:leave, player:avatar, player:ready, room:settings, match:start

Klient → server, hra

match:loaded, player:input, player:interact, state:sync, match:returnToLobby

Klient → server, relace

session:resume s tajným tokenem

Server → klient, řízení

rooms:snapshot, room:state, match:init, match:countdown, match:finished, room:closed, session:replaced

Server → klient, hra

world:snapshot, combat:event, player:died, player:respawned



Protokol verzovat (protocolVersion, buildId) a před zápasem ověřit také verzi mapy a assetů. Klient se starým nekompatibilním buildem dostane srozumitelnou výzvu k aktualizaci. U každé zprávy stanovit schéma, maximální velikost, potřebnou fázi, oprávnění a způsob potvrzení.

9. Výpadky, odchod a správa místností

V první verzi nemusí být diváci, chat, hlas, veřejné žebříčky ani trvalé ukládání statistik. Nejsou podmínkou uvedeného režimu.

10. PWA, ovládání a izolace singleplayeru

Offline musí dál fungovat celá původní kampaň. Multiplayer při nedostupném backendu zobrazí stav připojení a návrat do menu; nesmí blokovat spuštění singleplayeru. Socket.IO připojení nevytvářet při samotném hraní kampaně.

Stávající service worker ze scripts/pwa.ts už obsluhuje jen vybrané statické soubory. Zachovat tento princip a testem výslovně vyloučit /socket.io/, /api/ a /health z ukládání do cache. Pozvánku řešit query parametrem, aby fungovala i při současném statickém routování. Multiplayerové atlasy načítat podle potřeby; při změně seznamu precache nezhoršit offline dostupnost kampaně.

setupPwa dnes dostává callback pro pauzu hry. Multiplayer potřebuje vlastní reakci: aktualizaci odložit do lobby nebo po konci zápasu, neprovádět vynucený reload uprostřed boje. Escape, ztráta pointer locku, přepnutí aplikace a otočení telefonu okamžitě zruší aktivní vstupy. Menu ani skrytý panel nezastaví serverový čas.

Zachovat současné joystickové ovládání, výběr zbraní a sbírání. Přidat kompaktní skóre, zbývající čas, počet připojených lidí, stav spojení a portrét vlastního hráče. Na mobilu musí být lobby i výsledky ovladatelné na výšku i na šířku a respektovat bezpečné okraje displeje. Lokální asistence míření nesmí měnit serverové poškození ani dosah.

11. Technologie a nasazení podle krysi-jmena

Cílový provoz

Oblast

Návrh pro BUNKER 07

Runtime

Node.js 24 v image node:24-bookworm-slim, Express 5, Socket.IO 4; konkrétní verze uzamknout lockfilem.

Klient

Současný Vite + TypeScript, přidat socket.io-client kompatibilní se serverem.

Serverový build

TypeScript; například samostatný esbuild bundle pro Node 24 s externími npm závislostmi. Oddělená kontrola typů serveru bez DOM.

Server

Stejný SSH cíl jako reference a současná hra: ubuntu@130.61.169.112; dostupné prostředky a port ověřit před nasazením.

Adresa

Zachovat https://bunker07.rozd.cz/.

Backend

Navržený volný port 127.0.0.1:3001; reference používá 3000. Dostupnost 3001 zatím nebyla ověřena.

Compose

Vlastní projekt bunker07, jeden proces, Linux host networking a naslouchání výhradně na loopbacku jako v referenci.

Proxy

Stávající Nginx servíruje statickou hru, /socket.io/ , /api/ a /health posílá do backendu. HTTPS a certifikát zachovat.

Soubory

Nové /www/bunker07/releases/<releaseId>/, /www/bunker07/current, /www/bunker07/backups/. Nginx přepnout ze současného kořene na frontend aktivního releasu.

Stav

Místnosti a relace pouze v RAM. Žádné sdílení procesu ani paměti s krysi-jmena.



Zachovat statické servírování kampaně Nginxem, takže výpadek backendu nevyřadí offline ani běžný singleplayer. Převzatý kontejnerový vzor rozšířit o build Vite, kontrolu TypeScriptu, multiplayerové testy a vytvoření serverového bundle. Ověřit, že bundle neobsahuje browserové moduly a spustí se v čistém runtime image.

Převzít běh jako neprivilegovaný uživatel node, read-only filesystem, tmpfs, omezení oprávnění, restart po rebootu, healthcheck a rotaci logů. Počáteční rozpočet CPU/RAM určit zátěžovou zkouškou; nepřebírat bez měření 256 MiB z tahové hry. Logovat verzi, chyby a výkon, nikoli tokeny.

Postup nasazení

  1. Připravit deploy.bat a deploy/deploy.ps1 podle reference, se samostatnými názvy a cestami BUNKER 07. Budoucí npm run deploy je může volat; současný statický postup uchovat pod jasně pojmenovaným příkazem pro návrat.

  2. Vytvořit zdrojový archiv bez node_modules, Git metadat a lokálních konfigurací s tajnými údaji. Nahrát SCP, ověřit SHA-256, rozbalit release a sjednotit oprávnění stejně jako v referenci.

  3. Na serveru provést Docker build nativní pro jeho architekturu. Povinná kontrolní fáze: npm ci, stávající i nové testy, kontroly typů, frontendový a serverový build. Pro provoz ponechat jen produkční závislosti a sestavené soubory.

  4. Ještě před výměnou běžící verze zapnout režim údržby pro nové místnosti a starty. Počkat na konec aktivních zápasů, nebo hráčům oznámit plánované ukončení s odpočtem. Sestavení samotné nesmí restartovat běžící hru.

  5. Spustit nový kontejner, ověřit lokální /health s verzí protokolu a buildu. Propojení nového frontendového releasu a backendu kontrolovat stejným buildId; během přechodu odmítnout nekompatibilní klienty s výzvou k obnově.

  6. Při první migraci zálohovat existující konfiguraci bunker07.rozd.cz, ověřit očekávaný stav a upravit pouze tento virtual host. Přidat proxy a nový statický kořen, provést nginx -t a reload. Nedotýkat se konfigurace rat.rozd.cz ani dalších webů.

  7. Teprve po lokálních kontrolách přepnout current na nový release a ověřit veřejné HTTPS, statické assety, worker, Socket.IO polling i upgrade na WSS. Při chybě obnovit předchozí symlink, kontejner i případně Nginx konfiguraci.

  8. Ověřit založení lobby, vstup druhého izolovaného klienta, start, pohyb a konec testovacího zápasu; testovací místnost následně uklidit. Statické ověření samo nepotvrzuje funkčnost hry.

  9. Uchovat předchozí release a postup návratu. Při první migraci uchovat i původní statické soubory a konfiguraci; rollback musí umět stav před zavedením Docker backendu.

/socket.io/ musí dostat HTTP/1.1, hlavičky Upgrade a Connection, vypnuté proxy buffering a timeout delší než součet Socket.IO heartbeat intervalů, například 120 sekund. Cesta musí být stejná na klientovi, serveru i proxy. Podklad: Socket.IO za Nginxem.

ALLOWED_ORIGIN=https://bunker07.rozd.cz, TRUST_PROXY=loopback; Nginx přepíše X-Real-IP. Žádný nový veřejný backendový port. Zachovat dnešní pravidla cache pro HTML, hashované assety, manifest a worker. Starší hashované soubory ponechat dostupné pro otevřené klienty a offline cache také po přepnutí releasu, například sdíleným úložištěm assetů; samotné ponechání staré složky mimo kořen Nginxu nestačí.

Každá výměna backendového procesu zruší neuložené místnosti a relace. Údržbový režim má omezit přerušení, nejde o bezvýpadkovou migraci rozehrané simulace. Tento plán neobsahuje skutečné připojení k serveru ani tvrzení o jeho aktuálním stavu.

12. Validace a ochrana serveru

13. Navržené soubory a postup implementace

Názvy nových souborů jsou orientační; rozhraní upravit po vyčlenění čistého jádra.

src/
main.ts výběr režimu a životní cyklus klienta
ui/multiplayerLobby.ts seznam her, obličeje, připravenost
ui/multiplayerResults.ts skóre a odveta
multiplayer/
MultiplayerGame.ts propojení vstupů, rendereru a sítě
connection.ts Socket.IO, relace a potvrzené příkazy
prediction.ts místní predikce a opravy pohybu
interpolation.ts plynulý pohyb ostatních postav
shared/
protocol.ts typy a verze zpráv
multiplayerRules.ts pravidla zápasu, společné konstanty
simulation/ čisté jádro bez browserových závislostí
levels/multiplayerArena01.ts geometrie a spawn sektory
assets/multiplayerAvatars.ts osm tváří a jednotná AI kukla
server/
index.ts Express, Socket.IO, health, ukončení
config.ts port, origin, kapacity, časové limity
rooms.ts registry, hostitel, připravenost
sessions.ts anonymní tokeny a návrat
handlers.ts validace a routování příkazů
match.ts pevný krok, svět, výsledky
ai.ts výběr více cílů a události AI
spawns.ts výběr bezpečných startů a respawnů
Dockerfile
compose.yaml
deploy.bat
deploy/ release, proxy, ověření a rollback
tests/multiplayer/ simulace, protokol, integrace a zátěž

Etapy a podmínky dokončení

Etapa

Práce

Podmínka dokončení

1. Oddělení režimů

Menu, samostatný multiplayerový řadič, začátek sdíleného jádra, kontrola serverového sestavení.

Kampaň funguje jako dosud včetně offline; serverové jádro jde spustit bez DOM.

2. Lobby

Převzetí Express/Socket.IO, místnosti, tokeny, osm unikátních obličejů, připravenost, pozvánky, hostitel.

Dva až osm izolovaných klientů vstoupí, devátý je odmítnut; souběžná rezervace tváře je korektní.

3. Síťový pohyb

Pevný krok, protokol, predikce, interpolace, kolize a serverové spawny. Dočasně lze použít existující mapu.

Osm postav sdílí svět, neprochází zdmi a klient si nezrychlí pohyb.

4. Souboj lidí

Zásahy pistolí, pak ostatní zbraně, inventář, výbušniny, smrt, skóre, respawn a kompenzace zpoždění.

Dva lidé se mohou potkat a porazit, všichni vidí stejné výsledky; žádné dvojí zabití nebo sběr.

5. Aréna a AI

Nová mapa, ověření startů, vícecílá AI, kukla, kořist a obnova zásob.

AI má společný vzhled, zachované profily a běží jednou; mapa je hratelná pro dva i osm lidí.

6. Celý zápas

Čas a limit fragů, výsledky, odveta, reconnect, odchody, hostitel a úklid místností.

Celý cyklus lobby → zápas → výsledky → lobby proběhne bez ztráty či duplikace účastníků.

7. Mobil a provoz

PWA, dotykové ovládání, výkon, Docker/SSH deploy, Nginx a rollback.

Úspěšné kontroly na PC i fyzickém mobilu, zátěžový test a ověřený návrat verze.



První interní hratelný milník po etapě 4: lobby, dvě unikátní tváře, společná mapa, pistole, vzájemné zásahy, smrt a respawn. Dokončené zadání vyžaduje také osm účastníků, arénu, maskovanou AI, celý průběh zápasu a nasazovací postup.

14. Ověření a kritéria přijetí

Automatické kontroly

Herní, síťové a provozní zkoušky

Hotovo znamená

Hráč si v menu vybere multiplayer, založí nebo najde lobby, zvolí unikátní obličej a bez zadávání jména odehraje s dalšími 1–7 lidmi společný deathmatch. Všichni začínají s pistolí na různých bezpečných okrajích mapy, mohou bojovat mezi sebou, získávat výzbroj a potkávat jednotně maskované AI se známým chováním. Shodují se na zásazích, smrti, kořisti i výsledcích. Po zápase mohou hrát odvetu. Původní singleplayer včetně offline hraní zůstává funkční. Nasazení používá infrastrukturu podle krysi-jmena, vlastní izolovaný backend a ověřený postup návratu předchozí verze.