fix: grammar mistakes

This commit is contained in:
Martin Slachta
2026-08-05 20:03:14 +02:00
parent 22abb9b1c3
commit bb43a5bf77
14 changed files with 441 additions and 316 deletions
+3
View File
@@ -16,3 +16,6 @@ dist:
@rm -f kidiplom.zip @rm -f kidiplom.zip
@zip -r kidiplom.zip kidiplom @zip -r kidiplom.zip kidiplom
@rm -r -f kidiplom @rm -r -f kidiplom
fix:
sed -i -E 's/\b([ksvzaiouKSVZAIOU]) /\1~/g' kidiplom.tex
+81
View File
@@ -0,0 +1,81 @@
# Soubory
Adresář obsahuje soubory se zdrojovými kódy, sestavené spustitelné aplikace a zdrojový kód pro textovou část diplomové práce. Doporučujeme použít už sestavené soubory, které jsou připravené pro "čistou" instalaci `ubuntu-desktop-24.04.ova`.
# Sestavení
Veškeré spustitelné soubory jsou pro Linux. Už sestavené soubory jsou v adresáři `build/`. Zdrojové kódy jsou v adresáři `src/`. Projekt lze sestavit klasicky lokálně nebo kompletně přes Docker.
## Lokálně
Pro standartní sestavení je potřeba Conan, CMake a moderní kompiler, jako CLang nebo GCC. Projekt využívá verzi C++23.
Conan slouží pro získání konkrétních verzí balíčků jako ProtoBuf a SDL3. Sestavení tak začíná tím, že Conan potřebné balíčky stáhne a vytvoří konfigurační soubory pro CMake. Lze použít tento příkaz, který konfigurační soubory umístí do adresáře `./build/`.
```bash
$ conan install . --output-folder=build --build=missing -s build_type=Debug
```
Poté je potřeba adresář `build/` připravit pro CMake.
```bash
$ cmake -S . -B ./build -DCMAKE_TOOLCHAIN_FILE="build/conan_toolchain.cmake" -DCMAKE_BUILD_TYPE=Debug
```
Nakonec lze projekt sestavit pomocí:
```bash
$ cmake --build ./build
```
## Docker
Druhou variantou je použít Docker. V adresáři zdrojových kódů je podadresář `docker/`. Ten obsahuje Dockerfile pro sestavení i export spustitelných souborů. Pro sestavení nás zajímá jeho fáze `builder`. Sestavíme obraz `tw_builder` s tagem `jammy` pomocí příkazu:
```
$ docker build -f docker/Dockerfile --target builder -t tw_builder:jammy .
```
Pro získání sestavených souborů z Docker obrazu je nejjednodušší použít poslední fázi `export` Dockerfile a definovat `--output`. Konkrétně v tomto případě budou soubory vyexportovány do podadresáře `./dist/`.
```
$ docker build -f docker/Dockerfile --target export --output type=local,dest=dist .
```
# Spuštění
Pro spuštění již připravených spustitelných souborů v adresáři `build/`, není třeba na připravené "čisté" instalaci Ubuntu 22 nic měnit.
## Server
Pro hru více hráčů je nutné mít spuštěný `tw_server`. Ten také najdeme v adresáři `build/`. Pro jeho spuštění je třeba mít nainstalovanou knihovnu `libpq5`. V připravené instalaci Ubuntu 22 stačí tento balíček nainstalovat.
```
# apt install libpq5
```
Server po spuštění vypíše port, který pro hráče otevřel. Příklad výstupu po spuštění:
```
[2026-08-05 16:28:09.874] [info] quicr-port=8101 cluster-port=8102 timescaledb=disabled
[2026-08-05 16:28:10.034] [info] Running on port: 8101
[2026-08-05 16:28:10.035] [info] ZoneClusterLink listening on port 8102
[2026-08-05 16:28:10.063] [info] Registered as zone 1 (-5000,-5000) (0,5000)
```
Zajímá nás řádek s `Running on port`.
## Klient
Aplikace klienta je `tw_client`. Po spuštění uvidíte textové pole pro zadání adresy serveru, včetně portu. Klikněte na `Connect` pro připojení na server. Pokud se podaří, dostanete se do hry a uvidíte hráče jako červené kostky.
## Stress-testing
V adresáři `build/` je připravený i spustitelný soubor pro stress-testing, který naváže a simuluje určitý počet připojení na konkrétní server. Simulovaní hráči se i pohybují. Příklad testu pro server na 127.0.0.1:8101 s 300 simulovanými hráči.
```
$ ./tw_mock_client 300 127.0.0.1 8101
```
+23 -2
View File
@@ -40,8 +40,8 @@ urldate = {2026-08-03},
isbn = {978-0128182000} isbn = {978-0128182000}
} }
@ONLINE{interpolation, @ONLINE{interpolation1,
author = {Fiedler, Glenn}, author = {Glenn Fiedler},
title = {Snapshot Interpolation}, title = {Snapshot Interpolation},
year = {2015}, year = {2015},
url = {https://www.gafferongames.com/post/snapshot_interpolation/}, url = {https://www.gafferongames.com/post/snapshot_interpolation/},
@@ -49,6 +49,15 @@ isbn = {978-0128182000}
hyphenation = {english} hyphenation = {english}
} }
@ONLINE{interpolation2,
author = {Gabriel Gambetta},
title = {Entity Interpolation},
year = {2026},
url = {https://www.gabrielgambetta.com/entity-interpolation.html},
urldate = {2026-08-03},
hyphenation = {english}
}
@ONLINE{evolveheirachy, @ONLINE{evolveheirachy,
author = {West, Mick}, author = {West, Mick},
title = {Evolve Your Hierarchy}, title = {Evolve Your Hierarchy},
@@ -95,3 +104,15 @@ isbn = {978-0128182000}
urldate = {2026-08-03}, urldate = {2026-08-03},
hyphenation = {english} hyphenation = {english}
} }
@INPROCEEDINGS{assiotis06mmorpg,
author = {Assiotis, Marios and Tzanov, Velin},
title = {A Distributed Architecture for MMORPG},
booktitle = {NETGAMES '06: Proceedings of the 5th Workshop on Network and System Support for Games},
year = {2006},
location = {Singapore},
publisher = {ACM},
url = {https://www.comp.nus.edu.sg/~bleong/hydra/related/assiotis06mmorpg.pdf},
urldate = {2026-08-05},
hyphenation = {english}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+89 -81
View File
@@ -71,124 +71,132 @@
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces QUIC handshake}}{20}{figure.4}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces QUIC handshake}}{20}{figure.4}\protected@file@percent }
\newlabel{fig:quic_handshake}{{4}{20}{QUIC handshake}{figure.4}{}} \newlabel{fig:quic_handshake}{{4}{20}{QUIC handshake}{figure.4}{}}
\BKM@entry{id=22,open,dest={73656374696F6E2E34},srcline={575}}{5C3337365C3337375C303030345C3030305C3034305C303030485C303030725C30303061} \BKM@entry{id=22,open,dest={73656374696F6E2E34},srcline={575}}{5C3337365C3337375C303030345C3030305C3034305C303030485C303030725C30303061}
\BKM@entry{id=23,open,dest={73756273656374696F6E2E342E31},srcline={590}}{5C3337365C3337375C303030345C3030302E5C303030315C3030305C3034305C303030455C3030306E5C303030675C303030695C3030306E5C30303065} \BKM@entry{id=23,open,dest={73756273656374696F6E2E342E31},srcline={581}}{5C3337365C3337375C303030345C3030302E5C303030315C3030305C3034305C303030455C3030306E5C303030675C303030695C3030306E5C30303065}
\abx@aux@cite{0}{peekingvalorant}
\abx@aux@segm{0}{0}{peekingvalorant}
\BKM@entry{id=24,open,dest={73756273756273656374696F6E2E342E312E31},srcline={615}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030315C3030305C3034305C303030465C303030795C3030307A5C303030695C303030635C3030306B5C3030305C3337355C3030305C3034305C303030655C3030306E5C303030675C303030695C3030306E5C30303065}
\@writefile{toc}{\contentsline {section}{\numberline {4}Hra}{21}{section.4}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {4}Hra}{21}{section.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Engine}{21}{subsection.4.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Engine}{21}{subsection.4.1}\protected@file@percent }
\BKM@entry{id=24,open,dest={73756273756273656374696F6E2E342E312E31},srcline={624}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030315C3030305C3034305C303030465C303030795C3030307A5C303030695C303030635C3030306B5C3030305C3337355C3030305C3034305C303030655C3030306E5C303030675C303030695C3030306E5C30303065} \@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.1}Fyzický engine}{21}{subsubsection.4.1.1}\protected@file@percent }
\BKM@entry{id=25,open,dest={73756273756273656374696F6E2E342E312E32},srcline={632}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030325C3030305C3034305C303030565C303030795C3030306B5C303030725C303030655C303030735C3030306C5C3030306F5C303030765C3030305C3334315C3030306E5C3030305C333535} \BKM@entry{id=25,open,dest={73756273756273656374696F6E2E342E312E32},srcline={623}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030325C3030305C3034305C303030565C303030795C3030306B5C303030725C303030655C303030735C3030306C5C3030306F5C303030765C3030305C3334315C3030306E5C3030305C333535}
\BKM@entry{id=26,open,dest={73756273756273656374696F6E2E342E312E33},srcline={631}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030335C3030305C3034305C303030455C3030306E5C303030745C303030695C303030745C303030795C3030302D5C303030435C3030306F5C3030306D5C303030705C3030306F5C3030306E5C303030655C3030306E5C303030745C3030302D5C303030535C303030795C303030735C303030745C303030655C3030306D}
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces Architektura hry pro jednoho hráče}}{22}{figure.5}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces Architektura hry pro jednoho hráče}}{22}{figure.5}\protected@file@percent }
\newlabel{fig:single_player_game}{{5}{22}{Architektura hry pro jednoho hráče}{figure.5}{}} \newlabel{fig:single_player_game}{{5}{22}{Architektura hry pro jednoho hráče}{figure.5}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.1}Fyzický engine}{22}{subsubsection.4.1.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.2}Vykreslování}{22}{subsubsection.4.1.2}\protected@file@percent }
\BKM@entry{id=26,open,dest={73756273756273656374696F6E2E342E312E33},srcline={640}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030335C3030305C3034305C303030455C3030306E5C303030745C303030695C303030745C303030795C3030302D5C303030435C3030306F5C3030306D5C303030705C3030306F5C3030306E5C303030655C3030306E5C303030745C3030302D5C303030535C303030795C303030735C303030745C303030655C3030306D} \@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.3}Entity-Component-System}{22}{subsubsection.4.1.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.2}Vykreslování}{23}{subsubsection.4.1.2}\protected@file@percent } \newlabel{code:entt}{{1}{23}{Příklad použití knihovny Entt}{lstlisting.1}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.3}Entity-Component-System}{23}{subsubsection.4.1.3}\protected@file@percent } \@writefile{lol}{\contentsline {lstlisting}{\numberline {1}Příklad použití knihovny Entt}{23}{lstlisting.1}\protected@file@percent }
\BKM@entry{id=27,open,dest={73756273756273656374696F6E2E342E312E34},srcline={681}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030345C3030305C3034305C303030495C3030306D5C303030475C303030755C30303069} \BKM@entry{id=27,open,dest={73756273756273656374696F6E2E342E312E34},srcline={672}}{5C3337365C3337375C303030345C3030302E5C303030315C3030302E5C303030345C3030305C3034305C303030495C3030306D5C303030475C303030755C30303069}
\newlabel{code:entt}{{1}{24}{Příklad použití knihovny Entt}{lstlisting.1}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}Příklad použití knihovny Entt}{24}{lstlisting.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.4}ImGui}{24}{subsubsection.4.1.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.4}ImGui}{24}{subsubsection.4.1.4}\protected@file@percent }
\BKM@entry{id=28,open,dest={73656374696F6E2E35},srcline={700}}{5C3337365C3337375C303030355C3030305C3034305C303030485C303030725C303030615C3030305C3034305C303030765C3030305C3335355C303030635C303030655C3030305C3034305C303030685C303030725C3030305C3334315C3030315C3031355C3030315C313537} \BKM@entry{id=28,open,dest={73656374696F6E2E35},srcline={691}}{5C3337365C3337375C303030355C3030305C3034305C303030485C303030725C303030615C3030305C3034305C303030765C3030305C3335355C303030635C303030655C3030305C3034305C303030685C303030725C3030305C3334315C3030315C3031355C3030315C313537}
\BKM@entry{id=29,open,dest={73756273656374696F6E2E352E31},srcline={721}}{5C3337365C3337375C303030355C3030302E5C303030315C3030305C3034305C303030535C303030655C303030725C303030765C303030655C30303072} \BKM@entry{id=29,open,dest={73756273656374696F6E2E352E31},srcline={712}}{5C3337365C3337375C303030355C3030302E5C303030315C3030305C3034305C303030535C303030655C303030725C303030765C303030655C30303072}
\@writefile{toc}{\contentsline {section}{\numberline {5}Hra více hráčů}{26}{section.5}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {5}Hra více hráčů}{25}{section.5}\protected@file@percent }
\BKM@entry{id=30,open,dest={73756273756273656374696F6E2E352E312E31},srcline={731}}{5C3337365C3337375C303030355C3030302E5C303030315C3030302E5C303030315C3030305C3034305C303030525C303030655C303030675C303030695C303030735C303030745C303030725C3030305C3034305C3030306B5C3030306C5C303030695C303030655C3030306E5C303030745C3030315C313537} \@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Server}{25}{subsection.5.1}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces Architektura hry pro více hráčů}}{27}{figure.6}\protected@file@percent } \BKM@entry{id=30,open,dest={73756273756273656374696F6E2E352E312E31},srcline={722}}{5C3337365C3337375C303030355C3030302E5C303030315C3030302E5C303030315C3030305C3034305C303030525C303030655C303030675C303030695C303030735C303030745C303030725C3030305C3034305C3030306B5C3030306C5C303030695C303030655C3030306E5C303030745C3030315C313537}
\newlabel{fig:multi_player_game}{{6}{27}{Architektura hry pro více hráčů}{figure.6}{}} \BKM@entry{id=31,open,dest={73756273756273656374696F6E2E352E312E32},srcline={728}}{5C3337365C3337375C303030355C3030302E5C303030315C3030302E5C303030325C3030305C3034305C303030535C303030655C303030725C303030765C303030655C303030725C3030305C3034305C303030525C303030655C303030705C3030306C5C303030695C3030306B5C3030305C3334315C303030745C3030306F5C303030725C30303075}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Server}{27}{subsection.5.1}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces Architektura hry pro více hráčů}}{26}{figure.6}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.1}Registr klientů}{27}{subsubsection.5.1.1}\protected@file@percent } \newlabel{fig:multi_player_game}{{6}{26}{Architektura hry pro více hráčů}{figure.6}{}}
\BKM@entry{id=31,open,dest={73756273756273656374696F6E2E352E312E32},srcline={737}}{5C3337365C3337375C303030355C3030302E5C303030315C3030302E5C303030325C3030305C3034305C303030535C303030655C303030725C303030765C303030655C303030725C3030305C3034305C303030525C303030655C303030705C3030306C5C303030695C3030306B5C3030305C3334315C303030745C3030306F5C303030725C30303075} \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.1}Registr klientů}{26}{subsubsection.5.1.1}\protected@file@percent }
\BKM@entry{id=32,open,dest={73756273756273656374696F6E2E352E312E33},srcline={741}}{5C3337365C3337375C303030355C3030302E5C303030315C3030302E5C303030335C3030305C3034305C303030535C303030705C303030725C3030305C3334315C303030765C303030615C3030305C3034305C3030307A5C3030305C3334315C3030306A5C3030306D5C3030315C313537} \BKM@entry{id=32,open,dest={73756273756273656374696F6E2E352E312E33},srcline={732}}{5C3337365C3337375C303030355C3030302E5C303030315C3030302E5C303030335C3030305C3034305C303030535C303030705C303030725C3030305C3334315C303030765C303030615C3030305C3034305C3030307A5C3030305C3334315C3030306A5C3030306D5C3030315C313537}
\BKM@entry{id=33,open,dest={73756273656374696F6E2E352E32},srcline={751}}{5C3337365C3337375C303030355C3030302E5C303030325C3030305C3034305C3030304B5C3030306C5C303030695C303030655C3030306E5C30303074} \BKM@entry{id=33,open,dest={73756273656374696F6E2E352E32},srcline={742}}{5C3337365C3337375C303030355C3030302E5C303030325C3030305C3034305C3030304B5C3030306C5C303030695C303030655C3030306E5C30303074}
\BKM@entry{id=34,open,dest={73756273756273656374696F6E2E352E322E31},srcline={755}}{5C3337365C3337375C303030355C3030302E5C303030325C3030302E5C303030315C3030305C3034305C3030304B5C3030306C5C303030695C303030655C3030306E5C303030745C3030305C3034305C303030525C303030655C303030705C3030306C5C303030695C3030306B5C3030305C3334315C303030745C3030306F5C303030725C30303075} \BKM@entry{id=34,open,dest={73756273756273656374696F6E2E352E322E31},srcline={746}}{5C3337365C3337375C303030355C3030302E5C303030325C3030302E5C303030315C3030305C3034305C3030304B5C3030306C5C303030695C303030655C3030306E5C303030745C3030305C3034305C303030525C303030655C303030705C3030306C5C303030695C3030306B5C3030305C3334315C303030745C3030306F5C303030725C30303075}
\BKM@entry{id=35,open,dest={73756273756273656374696F6E2E352E322E32},srcline={759}}{5C3337365C3337375C303030355C3030302E5C303030325C3030302E5C303030325C3030305C3034305C303030495C3030306E5C303030745C303030655C303030725C303030705C3030306F5C3030306C5C303030615C303030635C30303065} \BKM@entry{id=35,open,dest={73756273756273656374696F6E2E352E322E32},srcline={750}}{5C3337365C3337375C303030355C3030302E5C303030325C3030302E5C303030325C3030305C3034305C303030495C3030306E5C303030745C303030655C303030725C303030705C3030306F5C3030306C5C303030615C303030635C30303065}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.2}Server Replikátoru}{28}{subsubsection.5.1.2}\protected@file@percent } \abx@aux@cite{0}{interpolation1}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.3}Správa zájmů}{28}{subsubsection.5.1.3}\protected@file@percent } \abx@aux@segm{0}{0}{interpolation1}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Klient}{28}{subsection.5.2}\protected@file@percent } \abx@aux@cite{0}{interpolation2}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.1}Klient Replikátoru}{28}{subsubsection.5.2.1}\protected@file@percent } \abx@aux@segm{0}{0}{interpolation2}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.2}Interpolace}{28}{subsubsection.5.2.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.2}Server Replikátoru}{27}{subsubsection.5.1.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.3}Správa zájmů}{27}{subsubsection.5.1.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Klient}{27}{subsection.5.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.1}Klient Replikátoru}{27}{subsubsection.5.2.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.2}Interpolace}{27}{subsubsection.5.2.2}\protected@file@percent }
\BKM@entry{id=36,open,dest={73756273756273656374696F6E2E352E322E33},srcline={767}}{5C3337365C3337375C303030355C3030302E5C303030325C3030302E5C303030335C3030305C3034305C303030525C3030306F5C3030306C5C3030306C5C303030625C303030615C303030635C3030306B} \BKM@entry{id=36,open,dest={73756273756273656374696F6E2E352E322E33},srcline={767}}{5C3337365C3337375C303030355C3030302E5C303030325C3030302E5C303030335C3030305C3034305C303030525C3030306F5C3030306C5C3030306C5C303030625C303030615C303030635C3030306B}
\BKM@entry{id=37,open,dest={73756273656374696F6E2E352E33},srcline={777}}{5C3337365C3337375C303030355C3030302E5C303030335C3030305C3034305C303030505C3030306F5C303030735C3030305C3335355C3030306C5C3030305C3334315C3030306E5C3030305C3335355C3030305C3034305C3030307A5C303030705C303030725C3030305C3334315C30303076} \BKM@entry{id=37,open,dest={73756273656374696F6E2E352E33},srcline={777}}{5C3337365C3337375C303030355C3030302E5C303030335C3030305C3034305C303030505C3030306F5C303030735C3030305C3335355C3030306C5C3030305C3334315C3030306E5C3030305C3335355C3030305C3034305C3030307A5C303030705C303030725C3030305C3334315C30303076}
\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces Graf interpolace}}{28}{figure.7}\protected@file@percent }
\newlabel{fig:interpolation}{{7}{28}{Graf interpolace}{figure.7}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.3}Rollback}{28}{subsubsection.5.2.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}Posílání zpráv}{28}{subsection.5.3}\protected@file@percent }
\BKM@entry{id=38,open,dest={73756273756273656374696F6E2E352E332E31},srcline={788}}{5C3337365C3337375C303030355C3030302E5C303030335C3030302E5C303030315C3030305C3034305C3030304B5C3030305C3336335C303030645C3030306F5C303030765C3030305C3334315C3030306E5C3030305C3335355C3030305C3034305C3030307A5C303030705C303030725C3030305C3334315C30303076} \BKM@entry{id=38,open,dest={73756273756273656374696F6E2E352E332E31},srcline={788}}{5C3337365C3337375C303030355C3030302E5C303030335C3030302E5C303030315C3030305C3034305C3030304B5C3030305C3336335C303030645C3030306F5C303030765C3030305C3334315C3030306E5C3030305C3335355C3030305C3034305C3030307A5C303030705C303030725C3030305C3334315C30303076}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.3}Rollback}{29}{subsubsection.5.2.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}Posílání zpráv}{29}{subsection.5.3}\protected@file@percent }
\BKM@entry{id=39,open,dest={73756273756273656374696F6E2E352E332E32},srcline={796}}{5C3337365C3337375C303030355C3030302E5C303030335C3030302E5C303030325C3030305C3034305C303030495C3030306D5C303030705C3030306C5C303030655C3030306D5C303030655C3030306E5C303030745C303030615C303030635C30303065} \BKM@entry{id=39,open,dest={73756273756273656374696F6E2E352E332E32},srcline={796}}{5C3337365C3337375C303030355C3030302E5C303030335C3030302E5C303030325C3030305C3034305C303030495C3030306D5C303030705C3030306C5C303030655C3030306D5C303030655C3030306E5C303030745C303030615C303030635C30303065}
\BKM@entry{id=40,open,dest={73756273756273656374696F6E2E352E332E33},srcline={800}}{5C3337365C3337375C303030355C3030302E5C303030335C3030302E5C303030335C3030305C3034305C303030445C303030655C303030745C303030655C3030306B5C303030635C303030655C3030305C3034305C303030615C3030305C3034305C3030306E5C3030305C3334315C303030705C303030725C303030615C303030765C303030615C3030305C3034305C303030635C303030685C303030795C30303062} \BKM@entry{id=40,open,dest={73756273756273656374696F6E2E352E332E33},srcline={800}}{5C3337365C3337375C303030355C3030302E5C303030335C3030302E5C303030335C3030305C3034305C303030445C303030655C303030745C303030655C3030306B5C303030635C303030655C3030305C3034305C303030615C3030305C3034305C3030306E5C3030305C3334315C303030705C303030725C303030615C303030765C303030615C3030305C3034305C303030635C303030685C303030795C30303062}
\BKM@entry{id=41,open,dest={73756273656374696F6E2E352E34},srcline={807}}{5C3337365C3337375C303030355C3030302E5C303030345C3030305C3034305C303030535C303030655C303030725C303030695C303030615C3030306C5C303030695C3030307A5C303030615C303030635C30303065} \BKM@entry{id=41,open,dest={73756273656374696F6E2E352E34},srcline={807}}{5C3337365C3337375C303030355C3030302E5C303030345C3030305C3034305C303030535C303030655C303030725C303030695C303030615C3030306C5C303030695C3030307A5C303030615C303030635C30303065}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.1}Kódování zpráv}{30}{subsubsection.5.3.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.1}Kódování zpráv}{29}{subsubsection.5.3.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.2}Implementace}{30}{subsubsection.5.3.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.2}Implementace}{29}{subsubsection.5.3.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.3}Detekce a náprava chyb}{30}{subsubsection.5.3.3}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.3.3}Detekce a náprava chyb}{29}{subsubsection.5.3.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.4}Serializace}{30}{subsection.5.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {5.4}Serializace}{30}{subsection.5.4}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}cpp}{31}{lstlisting.2}\protected@file@percent } \@writefile{lol}{\contentsline {lstlisting}{\numberline {2}cpp}{30}{lstlisting.2}\protected@file@percent }
\BKM@entry{id=42,open,dest={73756273656374696F6E2E352E35},srcline={841}}{5C3337365C3337375C303030355C3030302E5C303030355C3030305C3034305C303030505C303030725C3030306F5C303030745C3030306F5C3030306B5C3030306F5C3030306C5C3030305C3034305C303030515C303030555C303030495C303030435C30303072} \BKM@entry{id=42,open,dest={73756273656374696F6E2E352E35},srcline={841}}{5C3337365C3337375C303030355C3030302E5C303030355C3030305C3034305C303030505C303030725C3030306F5C303030745C3030306F5C3030306B5C3030306F5C3030306C5C3030305C3034305C303030515C303030555C303030495C303030435C30303072}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.5}Protokol QUICr}{31}{subsection.5.5}\protected@file@percent }
\BKM@entry{id=43,open,dest={73756273756273656374696F6E2E352E352E31},srcline={854}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030315C3030305C3034305C303030525C3030305C3334315C3030306D5C303030635C30303065} \BKM@entry{id=43,open,dest={73756273756273656374696F6E2E352E352E31},srcline={854}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030315C3030305C3034305C303030525C3030305C3334315C3030306D5C303030635C30303065}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.5}Protokol QUICr}{32}{subsection.5.5}\protected@file@percent }
\BKM@entry{id=44,open,dest={73756273756273656374696F6E2E352E352E32},srcline={867}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030325C3030305C3034305C303030485C303030615C3030306E5C303030645C303030735C303030685C303030615C3030306B5C30303065} \BKM@entry{id=44,open,dest={73756273756273656374696F6E2E352E352E32},srcline={867}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030325C3030305C3034305C303030485C303030615C3030306E5C303030645C303030735C303030685C303030615C3030306B5C30303065}
\BKM@entry{id=45,open,dest={73756273756273656374696F6E2E352E352E33},srcline={901}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030335C3030305C3034305C303030535C303030705C3030306F5C3030306C5C303030655C303030685C3030306C5C303030695C303030765C3030306F5C303030735C30303074} \BKM@entry{id=45,open,dest={73756273756273656374696F6E2E352E352E33},srcline={901}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030335C3030305C3034305C303030535C303030705C3030306F5C3030306C5C303030655C303030685C3030306C5C303030695C303030765C3030306F5C303030735C30303074}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.1}Rámce}{33}{subsubsection.5.5.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.1}Rámce}{32}{subsubsection.5.5.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.2}Handshake}{33}{subsubsection.5.5.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.2}Handshake}{32}{subsubsection.5.5.2}\protected@file@percent }
\newlabel{sec:quicr_handshake}{{5.5.2}{33}{Handshake}{subsubsection.5.5.2}{}} \newlabel{sec:quicr_handshake}{{5.5.2}{32}{Handshake}{subsubsection.5.5.2}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.3}Spolehlivost}{33}{subsubsection.5.5.3}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {8}{\ignorespaces Stavový stroj QUICr handshake}}{33}{figure.8}\protected@file@percent }
\newlabel{sec:quicr_reliability}{{5.5.3}{33}{Spolehlivost}{subsubsection.5.5.3}{}} \newlabel{fig:quicr_handshake}{{8}{33}{Stavový stroj QUICr handshake}{figure.8}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces Stavový stroj QUICr handshake}}{34}{figure.7}\protected@file@percent }
\newlabel{fig:quicr_handshake}{{7}{34}{Stavový stroj QUICr handshake}{figure.7}{}}
\BKM@entry{id=46,open,dest={73756273756273656374696F6E2E352E352E34},srcline={923}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030345C3030305C3034305C303030455C3030306E5C3030306B5C3030306F5C303030645C3030305C3335315C30303072} \BKM@entry{id=46,open,dest={73756273756273656374696F6E2E352E352E34},srcline={923}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030345C3030305C3034305C303030455C3030306E5C3030306B5C3030306F5C303030645C3030305C3335315C30303072}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.3}Spolehlivost}{34}{subsubsection.5.5.3}\protected@file@percent }
\newlabel{sec:quicr_reliability}{{5.5.3}{34}{Spolehlivost}{subsubsection.5.5.3}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.4}Enkodér}{34}{subsubsection.5.5.4}\protected@file@percent }
\BKM@entry{id=47,open,dest={73756273756273656374696F6E2E352E352E35},srcline={931}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030355C3030305C3034305C303030545C303030655C303030735C303030745C3030306F5C303030765C3030305C3334315C3030306E5C3030305C333535} \BKM@entry{id=47,open,dest={73756273756273656374696F6E2E352E352E35},srcline={931}}{5C3337365C3337375C303030355C3030302E5C303030355C3030302E5C303030355C3030305C3034305C303030545C303030655C303030735C303030745C3030306F5C303030765C3030305C3334315C3030306E5C3030305C333535}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.4}Enkodér}{35}{subsubsection.5.5.4}\protected@file@percent }
\BKM@entry{id=48,open,dest={73756273656374696F6E2E352E36},srcline={972}}{5C3337365C3337375C303030355C3030302E5C303030365C3030305C3034305C303030485C3030306F5C303030725C303030695C3030307A5C3030306F5C3030306E5C303030745C3030305C3334315C3030306C5C3030306E5C3030305C3335355C3030305C3034305C3030315C3134315C3030306B5C3030305C3334315C3030306C5C3030306F5C303030765C3030305C3334315C3030306E5C3030305C333535} \BKM@entry{id=48,open,dest={73756273656374696F6E2E352E36},srcline={972}}{5C3337365C3337375C303030355C3030302E5C303030365C3030305C3034305C303030485C3030306F5C303030725C303030695C3030307A5C3030306F5C3030306E5C303030745C3030305C3334315C3030306C5C3030306E5C3030305C3335355C3030305C3034305C3030315C3134315C3030306B5C3030305C3334315C3030306C5C3030306F5C303030765C3030305C3334315C3030306E5C3030305C333535}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.5}Testování}{35}{subsubsection.5.5.5}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.6}Horizontální škálování}{35}{subsection.5.6}\protected@file@percent }
\BKM@entry{id=49,open,dest={73756273656374696F6E2E352E37},srcline={992}}{5C3337365C3337375C303030355C3030302E5C303030375C3030305C3034305C303030565C3030305C3337355C303030735C3030306C5C303030655C303030645C3030306E5C3030305C3334315C3030305C3034305C303030685C303030725C30303061} \BKM@entry{id=49,open,dest={73756273656374696F6E2E352E37},srcline={992}}{5C3337365C3337375C303030355C3030302E5C303030375C3030305C3034305C303030565C3030305C3337355C303030735C3030306C5C303030655C303030645C3030306E5C3030305C3334315C3030305C3034305C303030685C303030725C30303061}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.5.5}Testování}{36}{subsubsection.5.5.5}\protected@file@percent } \newlabel{fig:zone_cluster_architecture}{{5.6}{36}{Horizontální škálování}{subsection.5.6}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.6}Horizontální škálování}{36}{subsection.5.6}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {9}{\ignorespaces Architektura systému s zone clusterem}}{36}{figure.9}\protected@file@percent }
\newlabel{fig:zone_cluster_architecture}{{5.6}{37}{Horizontální škálování}{subsection.5.6}{}} \@writefile{toc}{\contentsline {subsection}{\numberline {5.7}Výsledná hra}{36}{subsection.5.7}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {8}{\ignorespaces Architektura systému s zone clusterem}}{37}{figure.8}\protected@file@percent } \newlabel{fig:lobby_ui}{{5.7}{37}{Výsledná hra}{subsection.5.7}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.7}Výsledná hra}{37}{subsection.5.7}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {10}{\ignorespaces Uživatelské rozhraní v lobby}}{37}{figure.10}\protected@file@percent }
\newlabel{fig:lobby_ui}{{5.7}{38}{Výsledná hra}{subsection.5.7}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {9}{\ignorespaces Uživatelské rozhraní v lobby}}{38}{figure.9}\protected@file@percent }
\newlabel{fig:ui_showcase}{{5.7}{38}{Výsledná hra}{figure.9}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {10}{\ignorespaces Uživatelské rozhraní v klientovi}}{38}{figure.10}\protected@file@percent }
\BKM@entry{id=50,open,dest={73656374696F6E2E36},srcline={1016}}{5C3337365C3337375C303030365C3030305C3034305C3030304D5C3030315C3033335C3030315C3133315C3030315C3033335C3030306E5C3030305C333535} \BKM@entry{id=50,open,dest={73656374696F6E2E36},srcline={1016}}{5C3337365C3337375C303030365C3030305C3034305C3030304D5C3030315C3033335C3030315C3133315C3030315C3033335C3030306E5C3030305C333535}
\BKM@entry{id=51,open,dest={73756273656374696F6E2E362E31},srcline={1020}}{5C3337365C3337375C303030365C3030302E5C303030315C3030305C3034305C3030304D5C303030655C303030745C303030725C303030695C3030306B5C30303079} \BKM@entry{id=51,open,dest={73756273656374696F6E2E362E31},srcline={1020}}{5C3337365C3337375C303030365C3030302E5C303030315C3030305C3034305C3030304D5C303030655C303030745C303030725C303030695C3030306B5C30303079}
\BKM@entry{id=52,open,dest={73756273756273656374696F6E2E362E312E31},srcline={1028}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030315C3030305C3034305C303030505C3030306F5C303030735C303030745C303030675C303030725C303030655C303030535C303030515C3030304C} \BKM@entry{id=52,open,dest={73756273756273656374696F6E2E362E312E31},srcline={1028}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030315C3030305C3034305C303030505C3030306F5C303030735C303030745C303030675C303030725C303030655C303030535C303030515C3030304C}
\newlabel{fig:ui_showcase}{{5.7}{38}{Výsledná hra}{figure.10}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {11}{\ignorespaces Uživatelské rozhraní v klientovi}}{38}{figure.11}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {6}Měřění}{38}{section.6}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}Metriky}{38}{subsection.6.1}\protected@file@percent }
\BKM@entry{id=53,open,dest={73756273756273656374696F6E2E362E312E32},srcline={1032}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030325C3030305C3034305C303030545C303030695C3030306D5C303030655C303030735C303030635C303030615C3030306C5C303030655C303030445C30303042} \BKM@entry{id=53,open,dest={73756273756273656374696F6E2E362E312E32},srcline={1032}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030325C3030305C3034305C303030545C303030695C3030306D5C303030655C303030735C303030635C303030615C3030306C5C303030655C303030445C30303042}
\BKM@entry{id=54,open,dest={73756273756273656374696F6E2E362E312E33},srcline={1036}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030335C3030305C3034305C303030475C303030725C303030615C303030665C303030615C3030306E5C30303061} \BKM@entry{id=54,open,dest={73756273756273656374696F6E2E362E312E33},srcline={1036}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030335C3030305C3034305C303030475C303030725C303030615C303030665C303030615C3030306E5C30303061}
\@writefile{toc}{\contentsline {section}{\numberline {6}Měřění}{39}{section.6}\protected@file@percent } \BKM@entry{id=55,open,dest={73756273756273656374696F6E2E362E312E34},srcline={1048}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030345C3030305C3034305C303030545C303030725C303030615C303030635C30303079}
\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}Metriky}{39}{subsection.6.1}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {12}{\ignorespaces Příklad Grafana dashboardu}}{39}{figure.12}\protected@file@percent }
\newlabel{fig:grafana}{{12}{39}{Příklad Grafana dashboardu}{figure.12}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.1}PostgreSQL}{39}{subsubsection.6.1.1}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.1}PostgreSQL}{39}{subsubsection.6.1.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.2}TimescaleDB}{39}{subsubsection.6.1.2}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.2}TimescaleDB}{39}{subsubsection.6.1.2}\protected@file@percent }
\BKM@entry{id=55,open,dest={73756273756273656374696F6E2E362E312E34},srcline={1048}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030345C3030305C3034305C303030545C303030725C303030615C303030635C30303079} \@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.3}Grafana}{39}{subsubsection.6.1.3}\protected@file@percent }
\BKM@entry{id=56,open,dest={73756273756273656374696F6E2E362E312E35},srcline={1078}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030355C3030305C3034305C3030304B5C3030306C5C303030695C303030655C3030306E5C303030745C303030735C3030306B5C3030305C3334315C3030305C3034305C303030615C303030705C3030306C5C303030695C3030306B5C303030615C303030635C30303065} \BKM@entry{id=56,open,dest={73756273756273656374696F6E2E362E312E35},srcline={1078}}{5C3337365C3337375C303030365C3030302E5C303030315C3030302E5C303030355C3030305C3034305C3030304B5C3030306C5C303030695C303030655C3030306E5C303030745C303030735C3030306B5C3030305C3334315C3030305C3034305C303030615C303030705C3030306C5C303030695C3030306B5C303030615C303030635C30303065}
\BKM@entry{id=57,open,dest={73756273656374696F6E2E362E32},srcline={1082}}{5C3337365C3337375C303030365C3030302E5C303030325C3030305C3034305C303030515C303030555C303030495C303030435C30303072} \BKM@entry{id=57,open,dest={73756273656374696F6E2E362E32},srcline={1082}}{5C3337365C3337375C303030365C3030302E5C303030325C3030305C3034305C303030515C303030555C303030495C303030435C30303072}
\@writefile{lof}{\contentsline {figure}{\numberline {11}{\ignorespaces Příklad Grafana dashboardu}}{40}{figure.11}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {13}{\ignorespaces Jeden snímek v Tracy}}{40}{figure.13}\protected@file@percent }
\newlabel{fig:grafana}{{11}{40}{Příklad Grafana dashboardu}{figure.11}{}} \newlabel{fig:frame_in_tracy}{{13}{40}{Jeden snímek v Tracy}{figure.13}{}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.3}Grafana}{40}{subsubsection.6.1.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.4}Tracy}{40}{subsubsection.6.1.4}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.4}Tracy}{40}{subsubsection.6.1.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.5}Klientská aplikace}{40}{subsubsection.6.1.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {6.1.5}Klientská aplikace}{40}{subsubsection.6.1.5}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {12}{\ignorespaces Jeden snímek v Tracy}}{41}{figure.12}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {6.2}QUICr}{40}{subsection.6.2}\protected@file@percent }
\newlabel{fig:frame_in_tracy}{{12}{41}{Jeden snímek v Tracy}{figure.12}{}} \@writefile{lof}{\contentsline {figure}{\numberline {14}{\ignorespaces Porovnání odezvy TCP a QUICr}}{41}{figure.14}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {6.2}QUICr}{41}{subsection.6.2}\protected@file@percent } \newlabel{fig:latencycomparison}{{14}{41}{Porovnání odezvy TCP a QUICr}{figure.14}{}}
\newlabel{kod:tc}{{3}{41}{Příklad volání TC}{lstlisting.3}{}} \newlabel{kod:tc}{{3}{41}{Příklad volání TC}{lstlisting.3}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}Příklad volání TC}{41}{lstlisting.3}\protected@file@percent } \@writefile{lol}{\contentsline {lstlisting}{\numberline {3}Příklad volání TC}{41}{lstlisting.3}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {13}{\ignorespaces Porovnání odezvy TCP a QUICr}}{42}{figure.13}\protected@file@percent }
\newlabel{fig:latencycomparison}{{13}{42}{Porovnání odezvy TCP a QUICr}{figure.13}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {14}{\ignorespaces Porovnání integrace TCP a QUICr}}{42}{figure.14}\protected@file@percent }
\newlabel{fig:integrationcomparison}{{14}{42}{Porovnání integrace TCP a QUICr}{figure.14}{}}
\BKM@entry{id=58,open,dest={73756273656374696F6E2E362E33},srcline={1129}}{5C3337365C3337375C303030365C3030302E5C303030335C3030305C3034305C3030304F5C303030705C303030745C303030695C3030306D5C303030615C3030306C5C303030695C3030307A5C303030615C303030635C303030655C3030305C3034305C303030725C303030655C303030705C3030306C5C303030695C3030306B5C3030305C3334315C303030745C3030306F5C303030725C30303075} \BKM@entry{id=58,open,dest={73756273656374696F6E2E362E33},srcline={1129}}{5C3337365C3337375C303030365C3030302E5C303030335C3030305C3034305C3030304F5C303030705C303030745C303030695C3030306D5C303030615C3030306C5C303030695C3030307A5C303030615C303030635C303030655C3030305C3034305C303030725C303030655C303030705C3030306C5C303030695C3030306B5C3030305C3334315C303030745C3030306F5C303030725C30303075}
\@writefile{lof}{\contentsline {figure}{\numberline {15}{\ignorespaces 301 připojených hráčů}}{43}{figure.15}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {15}{\ignorespaces Porovnání integrace TCP a QUICr}}{42}{figure.15}\protected@file@percent }
\newlabel{fig:playerbenchmark}{{15}{43}{301 připojených hráčů}{figure.15}{}} \newlabel{fig:integrationcomparison}{{15}{42}{Porovnání integrace TCP a QUICr}{figure.15}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {6.3}Optimalizace replikátoru}{42}{subsection.6.3}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {16}{\ignorespaces 301 připojených hráčů}}{42}{figure.16}\protected@file@percent }
\newlabel{fig:playerbenchmark}{{16}{42}{301 připojených hráčů}{figure.16}{}}
\newlabel{fig:tracyreplicator}{{6.3}{43}{Optimalizace replikátoru}{subsection.6.3}{}} \newlabel{fig:tracyreplicator}{{6.3}{43}{Optimalizace replikátoru}{subsection.6.3}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {16}{\ignorespaces Analýza replikátoru}}{43}{figure.16}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {17}{\ignorespaces Analýza replikátoru}}{43}{figure.17}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {6.3}Optimalizace replikátoru}{43}{subsection.6.3}\protected@file@percent } \newlabel{fig:ecs_optimization_tracy_01}{{6.3}{43}{Optimalizace replikátoru}{figure.17}{}}
\newlabel{fig:ecs_optimization_tracy_01}{{6.3}{44}{Optimalizace replikátoru}{figure.16}{}} \@writefile{lof}{\contentsline {figure}{\numberline {18}{\ignorespaces Analýza optimalizace replikátoru pro ECS}}{43}{figure.18}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {17}{\ignorespaces Analýza optimalizace replikátoru pro ECS}}{44}{figure.17}\protected@file@percent }
\newlabel{fig:ecs_optimization_tracy_02}{{6.3}{44}{Optimalizace replikátoru}{figure.17}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {18}{\ignorespaces Analýza optimalizace replikátoru pro ECS}}{44}{figure.18}\protected@file@percent }
\BKM@entry{id=59,open,dest={73756273656374696F6E2E362E34},srcline={1184}}{5C3337365C3337375C303030365C3030302E5C303030345C3030305C3034305C3030304F5C303030705C303030745C303030695C3030306D5C303030615C3030306C5C303030695C3030307A5C303030615C303030635C303030655C3030305C3034305C3030306D5C303030615C3030306E5C303030615C3030315C3137365C303030655C303030725C303030615C3030305C3034305C3030307A5C3030305C3334315C3030306A5C3030306D5C3030315C313537} \BKM@entry{id=59,open,dest={73756273656374696F6E2E362E34},srcline={1184}}{5C3337365C3337375C303030365C3030302E5C303030345C3030305C3034305C3030304F5C303030705C303030745C303030695C3030306D5C303030615C3030306C5C303030695C3030307A5C303030615C303030635C303030655C3030305C3034305C3030306D5C303030615C3030306E5C303030615C3030315C3137365C303030655C303030725C303030615C3030305C3034305C3030307A5C3030305C3334315C3030306A5C3030306D5C3030315C313537}
\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Porovnání serializátorů}}{45}{table.1}\protected@file@percent } \newlabel{fig:ecs_optimization_tracy_02}{{6.3}{44}{Optimalizace replikátoru}{figure.18}{}}
\newlabel{t:serialization_comparison}{{1}{45}{Porovnání serializátorů}{table.1}{}} \@writefile{lof}{\contentsline {figure}{\numberline {19}{\ignorespaces Analýza optimalizace replikátoru pro ECS}}{44}{figure.19}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {6.4}Optimalizace manažera zájmů}{45}{subsection.6.4}\protected@file@percent } \@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Porovnání serializátorů}}{44}{table.1}\protected@file@percent }
\newlabel{t:serialization_comparison}{{1}{44}{Porovnání serializátorů}{table.1}{}}
\BKM@entry{id=60,open,dest={73756273656374696F6E2E362E35},srcline={1212}}{5C3337365C3337375C303030365C3030302E5C303030355C3030305C3034305C303030505C303030655C303030655C303030725C3030302D5C303030745C3030306F5C3030302D5C303030705C303030655C303030655C30303072} \BKM@entry{id=60,open,dest={73756273656374696F6E2E362E35},srcline={1212}}{5C3337365C3337375C303030365C3030302E5C303030355C3030305C3034305C303030505C303030655C303030655C303030725C3030302D5C303030745C3030306F5C3030302D5C303030705C303030655C303030655C30303072}
\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Porovnání algoritmů}}{46}{table.2}\protected@file@percent } \@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Porovnání algoritmů}}{45}{table.2}\protected@file@percent }
\newlabel{table:range_query_comparison}{{2}{46}{Porovnání algoritmů}{table.2}{}} \newlabel{table:range_query_comparison}{{2}{45}{Porovnání algoritmů}{table.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {6.5}Peer-to-peer}{46}{subsection.6.5}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {6.4}Optimalizace manažera zájmů}{45}{subsection.6.4}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {19}{\ignorespaces Porovnání TCP a QUICr v peer-to-peer}}{47}{figure.19}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {6.5}Peer-to-peer}{45}{subsection.6.5}\protected@file@percent }
\newlabel{fig:peer_to_peer}{{19}{47}{Porovnání TCP a QUICr v peer-to-peer}{figure.19}{}} \@writefile{lof}{\contentsline {figure}{\numberline {20}{\ignorespaces Porovnání TCP a QUICr v peer-to-peer}}{47}{figure.20}\protected@file@percent }
\newlabel{fig:peer_to_peer}{{20}{47}{Porovnání TCP a QUICr v peer-to-peer}{figure.20}{}}
\BKM@entry{id=61,open,dest={73656374696F6E2A2E33},srcline={1251}}{5C3337365C3337375C3030305A5C3030305C3334315C303030765C3030315C3033335C30303072} \BKM@entry{id=61,open,dest={73656374696F6E2A2E33},srcline={1251}}{5C3337365C3337375C3030305A5C3030305C3334315C303030765C3030315C3033335C30303072}
\abx@aux@cite{0}{quic} \abx@aux@cite{0}{quic}
\abx@aux@segm{0}{0}{quic} \abx@aux@segm{0}{0}{quic}
+5 -2
View File
@@ -2159,8 +2159,11 @@
<bcf:section number="0"> <bcf:section number="0">
<bcf:citekey order="1" intorder="1">computer_networks</bcf:citekey> <bcf:citekey order="1" intorder="1">computer_networks</bcf:citekey>
<bcf:citekey order="2" intorder="1">quic</bcf:citekey> <bcf:citekey order="2" intorder="1">quic</bcf:citekey>
<bcf:citekey order="3" intorder="1">quic</bcf:citekey> <bcf:citekey order="3" intorder="1">peekingvalorant</bcf:citekey>
<bcf:citekey order="4" intorder="1" nocite="1">*</bcf:citekey> <bcf:citekey order="4" intorder="1">interpolation1</bcf:citekey>
<bcf:citekey order="5" intorder="1">interpolation2</bcf:citekey>
<bcf:citekey order="6" intorder="1">quic</bcf:citekey>
<bcf:citekey order="7" intorder="1" nocite="1">*</bcf:citekey>
</bcf:section> </bcf:section>
<!-- SORTING TEMPLATES --> <!-- SORTING TEMPLATES -->
<bcf:sortingtemplate name="none"> <bcf:sortingtemplate name="none">
+12 -11
View File
@@ -1,18 +1,18 @@
# Fdb version 4 # Fdb version 4
["biber kidiplom"] 1777641420.71466 "kidiplom.bcf" "kidiplom.bbl" "kidiplom" 1785932392.98701 2 ["biber kidiplom"] 1777641420.71466 "kidiplom.bcf" "kidiplom.bbl" "kidiplom" 1785952957.89037 2
"kidiplom.bcf" 1785932392.85907 100697 0d278831f58b22e288d3858fcb2c1fe5 "pdflatex" "kidiplom.bcf" 1785952957.76815 100905 8b8612ca6bc94ca374c1ec6ab14072fc "pdflatex"
(generated) (generated)
"kidiplom.bbl" "kidiplom.bbl"
"kidiplom.blg" "kidiplom.blg"
(rewritten before read) (rewritten before read)
["makeindex kidiplom.idx"] 1777641420.69393 "kidiplom.idx" "kidiplom.ind" "kidiplom" 1785932392.98418 0 ["makeindex kidiplom.idx"] 1777641420.69393 "kidiplom.idx" "kidiplom.ind" "kidiplom" 1785952957.88708 0
"kidiplom.idx" 1785932390.72901 0 d41d8cd98f00b204e9800998ecf8427e "pdflatex" "kidiplom.idx" 1785952955.62613 0 d41d8cd98f00b204e9800998ecf8427e "pdflatex"
(generated) (generated)
"kidiplom.ilg" "kidiplom.ilg"
"kidiplom.ind" "kidiplom.ind"
(rewritten before read) (rewritten before read)
["pdflatex"] 1785932390.14512 "/home/martin/projects/kidiplom/kidiplom.tex" "kidiplom.pdf" "kidiplom" 1785932392.98432 2 ["pdflatex"] 1785952955.14657 "/home/martin/projects/kidiplom/kidiplom.tex" "kidiplom.pdf" "kidiplom" 1785952957.88722 2
"/home/martin/projects/kidiplom/kidiplom.tex" 1785932389.98899 130339 ced8bb79ff1aac0f7aa14c7e3e43c7dd "" "/home/martin/projects/kidiplom/kidiplom.tex" 1785952955.06412 129372 81e9d865e95d8094de837b4ca6c36899 ""
"/usr/share/texmf-dist/fonts/enc/dvips/base/8r.enc" 1775415801 4850 80dc9bab7f31fb78a000ccfed0e27cab "" "/usr/share/texmf-dist/fonts/enc/dvips/base/8r.enc" 1775415801 4850 80dc9bab7f31fb78a000ccfed0e27cab ""
"/usr/share/texmf-dist/fonts/enc/dvips/lm/lm-ec.enc" 1775415801 2375 baa924870cfb487815765f9094cf3728 "" "/usr/share/texmf-dist/fonts/enc/dvips/lm/lm-ec.enc" 1775415801 2375 baa924870cfb487815765f9094cf3728 ""
"/usr/share/texmf-dist/fonts/enc/dvips/lm/lm-mathit.enc" 1775415801 2405 5dcf2c1b967ee25cc46c58cd52244aed "" "/usr/share/texmf-dist/fonts/enc/dvips/lm/lm-mathit.enc" 1775415801 2405 5dcf2c1b967ee25cc46c58cd52244aed ""
@@ -253,6 +253,7 @@
"graphics/http2.pdf" 1785767496.10594 46800 91209613d245a76f155c3f9e6f79cdf6 "" "graphics/http2.pdf" 1785767496.10594 46800 91209613d245a76f155c3f9e6f79cdf6 ""
"graphics/http3.pdf" 1785767496.10594 79793 31bf8e82583c4435518e5143b8792c85 "" "graphics/http3.pdf" 1785767496.10594 79793 31bf8e82583c4435518e5143b8792c85 ""
"graphics/integrationcomparison.pdf" 1785767496.10694 21400 e9a5f98ce0119825ff32deab9aeb8849 "" "graphics/integrationcomparison.pdf" 1785767496.10694 21400 e9a5f98ce0119825ff32deab9aeb8849 ""
"graphics/interpolation.png" 1785951889.70366 17128 236f0c22113995d196ef39af0121366f ""
"graphics/kititle-cz-nofont.pdf" 1681557593 12762 4b9f69751f3c44debf721c7e80adffc7 "" "graphics/kititle-cz-nofont.pdf" 1681557593 12762 4b9f69751f3c44debf721c7e80adffc7 ""
"graphics/latencycomparison.pdf" 1785767496.10694 20418 cce68df2d0a9cefe2fb78a48a6bd216b "" "graphics/latencycomparison.pdf" 1785767496.10694 20418 cce68df2d0a9cefe2fb78a48a6bd216b ""
"graphics/layer_architecture.pdf" 1785767496.10694 18700 76efc7ba73621fe471df54327abb2b71 "" "graphics/layer_architecture.pdf" 1785767496.10694 18700 76efc7ba73621fe471df54327abb2b71 ""
@@ -269,15 +270,15 @@
"iso-numeric.cbx" 1681557593 73 45828f8df9dead5135d2c8a727f5b601 "" "iso-numeric.cbx" 1681557593 73 45828f8df9dead5135d2c8a727f5b601 ""
"iso.bbx" 1681557593 13233 9f9e9c852fe772bfe1efaacc6b415eb7 "" "iso.bbx" 1681557593 13233 9f9e9c852fe772bfe1efaacc6b415eb7 ""
"kibase.sty" 1681557593 23853 021ae8236751950ac5e18f6a5bcf1da7 "" "kibase.sty" 1681557593 23853 021ae8236751950ac5e18f6a5bcf1da7 ""
"kidiplom.aux" 1785932392.84007 33845 e7a8c4fb76a8d517b6202e30891f113d "pdflatex" "kidiplom.aux" 1785952957.74615 34253 c8e99647e9292a0e18575d06a58f17ab "pdflatex"
"kidiplom.bbl" 1785780010.56994 7686 c3cba72138b16e01160647867a8d8f99 "biber kidiplom" "kidiplom.bbl" 1785780010.56994 7686 c3cba72138b16e01160647867a8d8f99 "biber kidiplom"
"kidiplom.cls" 1681557593 18598 7684b2d13ac67d7b017c4eea1e12fa0c "" "kidiplom.cls" 1681557593 18598 7684b2d13ac67d7b017c4eea1e12fa0c ""
"kidiplom.glsdefs" 1777655247.6059 525 791a05cd0a9f8650067804d8f5ff3f41 "" "kidiplom.glsdefs" 1777655247.6059 525 791a05cd0a9f8650067804d8f5ff3f41 ""
"kidiplom.ind" 1785767496.11494 0 d41d8cd98f00b204e9800998ecf8427e "makeindex kidiplom.idx" "kidiplom.ind" 1785767496.11494 0 d41d8cd98f00b204e9800998ecf8427e "makeindex kidiplom.idx"
"kidiplom.lot" 1785932392.86181 387 126bd6bd943e275b2c6c6e0f31022a31 "pdflatex" "kidiplom.lot" 1785952957.76915 387 1ac32e7367846a270a0209a5b69d3838 "pdflatex"
"kidiplom.run.xml" 1785932392.86181 2535 4e001a965ee2f4de88dc6271855a61ea "pdflatex" "kidiplom.run.xml" 1785952957.76915 2535 4e001a965ee2f4de88dc6271855a61ea "pdflatex"
"kidiplom.tex" 1785932389.98899 130339 ced8bb79ff1aac0f7aa14c7e3e43c7dd "" "kidiplom.tex" 1785952955.06412 129372 81e9d865e95d8094de837b4ca6c36899 ""
"kidiplom.toc" 1785932392.86181 5374 4ebd5c75e3bf56c06e2972de702531f0 "pdflatex" "kidiplom.toc" 1785952957.76915 5374 313406824c830d1b9566208754d8e887 "pdflatex"
(generated) (generated)
"kidiplom.acn" "kidiplom.acn"
"kidiplom.aux" "kidiplom.aux"
+67 -61
View File
@@ -542,6 +542,7 @@ INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/lm/ec-lmr7.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/lm/ec-lmr7.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/lm/ec-lmbx10.tfm
INPUT ./graphics/single_player_game.pdf INPUT ./graphics/single_player_game.pdf
INPUT ./graphics/single_player_game.pdf INPUT ./graphics/single_player_game.pdf
INPUT ./graphics/single_player_game.pdf INPUT ./graphics/single_player_game.pdf
@@ -561,77 +562,82 @@ INPUT ./graphics/multi_player_game.pdf
INPUT ./graphics/multi_player_game.pdf INPUT ./graphics/multi_player_game.pdf
INPUT ./graphics/multi_player_game.pdf INPUT ./graphics/multi_player_game.pdf
INPUT ./graphics/multi_player_game.pdf INPUT ./graphics/multi_player_game.pdf
INPUT ./graphics/interpolation.png
INPUT ./graphics/interpolation.png
INPUT ./graphics/interpolation.png
INPUT ./graphics/interpolation.png
INPUT ./graphics/interpolation.png
INPUT ./graphics/quicr_handshake.pdf INPUT ./graphics/quicr_handshake.pdf
INPUT ./graphics/quicr_handshake.pdf INPUT ./graphics/quicr_handshake.pdf
INPUT ./graphics/quicr_handshake.pdf INPUT ./graphics/quicr_handshake.pdf
INPUT ./graphics/quicr_handshake.pdf INPUT ./graphics/quicr_handshake.pdf
INPUT ./graphics/quicr_handshake.pdf INPUT ./graphics/quicr_handshake.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT /usr/share/texmf-dist/fonts/tfm/adobe/courier/pcrb8t.tfm INPUT /usr/share/texmf-dist/fonts/tfm/adobe/courier/pcrb8t.tfm
INPUT /usr/share/texmf-dist/fonts/vf/adobe/courier/pcrb8t.vf
INPUT /usr/share/texmf-dist/fonts/tfm/adobe/courier/pcrb8r.tfm
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/zone_server_architecture.pdf
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/lobby_ui.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/ui_showcase.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/grafana.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/latencycomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/integrationcomparison.pdf
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/playerbenchmark.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/300playerstrace.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_01.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/ecs_optimization_tracy_02.png
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT ./graphics/peer_to_peer.pdf
INPUT /usr/share/texmf-dist/tex/latex/lm/ts1lmr.fd INPUT /usr/share/texmf-dist/tex/latex/lm/ts1lmr.fd
INPUT /usr/share/texmf-dist/tex/latex/lm/ts1lmr.fd INPUT /usr/share/texmf-dist/tex/latex/lm/ts1lmr.fd
INPUT /usr/share/texmf-dist/tex/latex/lm/ts1lmr.fd INPUT /usr/share/texmf-dist/tex/latex/lm/ts1lmr.fd
INPUT /usr/share/texmf-dist/fonts/tfm/public/lm/ts1-lmr12.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/lm/ts1-lmr12.tfm
INPUT /usr/share/texmf-dist/fonts/vf/adobe/courier/pcrb8t.vf
INPUT /usr/share/texmf-dist/fonts/tfm/adobe/courier/pcrb8r.tfm
INPUT /usr/share/texmf-dist/fonts/enc/dvips/lm/lm-ts1.enc INPUT /usr/share/texmf-dist/fonts/enc/dvips/lm/lm-ts1.enc
INPUT kidiplom.aux INPUT kidiplom.aux
INPUT kidiplom.run.xml INPUT kidiplom.run.xml
+70 -68
View File
@@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.29 (TeX Live 2026/Arch Linux) (preloaded format=pdflatex 2026.6.8) 5 AUG 2026 14:19 This is pdfTeX, Version 3.141592653-2.6-1.40.29 (TeX Live 2026/Arch Linux) (preloaded format=pdflatex 2026.6.8) 5 AUG 2026 20:02
entering extended mode entering extended mode
restricted \write18 enabled. restricted \write18 enabled.
%&-line parsing enabled. %&-line parsing enabled.
@@ -1543,50 +1543,37 @@ File: graphics/quic_handshake.pdf Graphic file (type pdf)
<use graphics/quic_handshake.pdf> <use graphics/quic_handshake.pdf>
Package pdftex.def Info: graphics/quic_handshake.pdf used on input line 465. Package pdftex.def Info: graphics/quic_handshake.pdf used on input line 465.
(pdftex.def) Requested size: 204.7506pt x 274.7626pt. (pdftex.def) Requested size: 204.7506pt x 274.7626pt.
[20 <./graphics/quic_handshake.pdf>] [21] [20 <./graphics/quic_handshake.pdf>]
LaTeX Font Info: External font `lmex10' loaded for size LaTeX Font Info: External font `lmex10' loaded for size
(Font) <10> on input line 614. (Font) <10> on input line 605.
LaTeX Font Info: External font `lmex10' loaded for size LaTeX Font Info: External font `lmex10' loaded for size
(Font) <7> on input line 614. (Font) <7> on input line 605.
LaTeX Font Info: External font `lmex10' loaded for size LaTeX Font Info: External font `lmex10' loaded for size
(Font) <5> on input line 614. (Font) <5> on input line 605.
Underfull \hbox (badness 10000) in paragraph at lines 614--614
[][][]\T1/lmr/m/n/10 ƒlánek od Riot Ga-mes uka-zuje, jak d·-le-ºitá je ode-zva
u kom-pe-te-tiv-
[]
Underfull \hbox (badness 10000) in paragraph at lines 614--614 LaTeX Warning: Citation 'peekingvalorant' on page 21 undefined on input line 60
\T1/lmr/m/n/10 ních her. U pro-fe-si-o-nál-ních hr᣷ je po-znat i roz-díl mezi 5.
120Hz a 240Hz.
[]
<graphics/single_player_game.pdf, id=323, 334.3692pt x 171.76169pt> <graphics/single_player_game.pdf, id=318, 334.3692pt x 171.76169pt>
File: graphics/single_player_game.pdf Graphic file (type pdf) File: graphics/single_player_game.pdf Graphic file (type pdf)
<use graphics/single_player_game.pdf> <use graphics/single_player_game.pdf>
Package pdftex.def Info: graphics/single_player_game.pdf used on input line 61 Package pdftex.def Info: graphics/single_player_game.pdf used on input line 60
8. 9.
(pdftex.def) Requested size: 327.60219pt x 168.29646pt. (pdftex.def) Requested size: 327.60219pt x 168.29646pt.
[21] [22 <./graphics/single_player_game.pdf>]
Overfull \hbox (9.23495pt too wide) in paragraph at lines 628--629
\T1/lmr/m/n/12 en-gine po-sune stav en-tit (zrych-lení a po-zice). V²e jsme oba
-lili do []
[]
[22 <./graphics/single_player_game.pdf>]
Package hyperref Info: bookmark level for unknown lstlisting defaults to 0 on i Package hyperref Info: bookmark level for unknown lstlisting defaults to 0 on i
nput line 649. nput line 640.
[23] [24] [25] [23] [24]
<graphics/multi_player_game.pdf, id=372, 385.44pt x 457.71pt> <graphics/multi_player_game.pdf, id=367, 385.44pt x 457.71pt>
File: graphics/multi_player_game.pdf Graphic file (type pdf) File: graphics/multi_player_game.pdf Graphic file (type pdf)
<use graphics/multi_player_game.pdf> <use graphics/multi_player_game.pdf>
Package pdftex.def Info: graphics/multi_player_game.pdf used on input line 714 Package pdftex.def Info: graphics/multi_player_game.pdf used on input line 705
. .
(pdftex.def) Requested size: 204.7506pt x 243.13689pt. (pdftex.def) Requested size: 204.7506pt x 243.13689pt.
[26] [27 <./graphics/multi_player_game.pdf>] [25] [26 <./graphics/multi_player_game.pdf>]
! Undefined control sequence. ! Undefined control sequence.
l.753 ...World}, která reprezentuje stav a \inlcp l.744 ...World}, která reprezentuje stav a \inlcp
{ClientWorldController}, k... {ClientWorldController}, k...
The control sequence at the end of the top line The control sequence at the end of the top line
of your error message was never \def'ed. If you have of your error message was never \def'ed. If you have
@@ -1594,7 +1581,20 @@ misspelled it (e.g., `\hobx'), type `I' and the correct
spelling (e.g., `I\hbox'). Otherwise just continue, spelling (e.g., `I\hbox'). Otherwise just continue,
and I'll forget about whatever was undefined. and I'll forget about whatever was undefined.
[28] [29]
LaTeX Warning: Citation 'interpolation1' on page 27 undefined on input line 752
.
LaTeX Warning: Citation 'interpolation2' on page 27 undefined on input line 752
.
<graphics/interpolation.png, id=392, 818.05624pt x 179.67125pt>
File: graphics/interpolation.png Graphic file (type png)
<use graphics/interpolation.png>
Package pdftex.def Info: graphics/interpolation.png used on input line 756.
(pdftex.def) Requested size: 409.50119pt x 89.93956pt.
[27] [28 <./graphics/interpolation.png>]
Overfull \hbox (8.12425pt too wide) in paragraph at lines 798--799 Overfull \hbox (8.12425pt too wide) in paragraph at lines 798--799
\T1/lmr/m/n/12 Vytvo°ili jsme t°ídu [][][][], která má na roz-hraní me-tody [] \T1/lmr/m/n/12 Vytvo°ili jsme t°ídu [][][][], která má na roz-hraní me-tody []
[] []
@@ -1605,75 +1605,80 @@ Overfull \hbox (20.39532pt too wide) in paragraph at lines 798--799
pro kon-cový bod [] pro kon-cový bod []
[] []
[30] [29]
LaTeX Warning: Reference `code:entity_spawn_message' on page 31 undefined on in LaTeX Warning: Reference `code:entity_spawn_message' on page 30 undefined on in
put line 815. put line 815.
[31] [32] [30] [31]
Overfull \hbox (23.67757pt too wide) in paragraph at lines 883--885
\T1/lmr/m/n/12 mo-ment £eká na po-tvr-zení, ºe spo-jení bylo na-vá-záno, tedy r
á-mec []
[]
<graphics/quicr_handshake.pdf, id=427, 337.26pt x 246.9225pt> <graphics/quicr_handshake.pdf, id=427, 337.26pt x 246.9225pt>
File: graphics/quicr_handshake.pdf Graphic file (type pdf) File: graphics/quicr_handshake.pdf Graphic file (type pdf)
<use graphics/quicr_handshake.pdf> <use graphics/quicr_handshake.pdf>
Package pdftex.def Info: graphics/quicr_handshake.pdf used on input line 895. Package pdftex.def Info: graphics/quicr_handshake.pdf used on input line 895.
(pdftex.def) Requested size: 409.50119pt x 299.82079pt. (pdftex.def) Requested size: 409.50119pt x 299.82079pt.
[33] [34 <./graphics/quicr_handshake.pdf>] [32] [33 <./graphics/quicr_handshake.pdf>]
Overfull \hbox (3.49525pt too wide) in paragraph at lines 905--906 Overfull \hbox (3.49525pt too wide) in paragraph at lines 905--906
[]\T1/lmr/m/n/12 Spolehlivost °e²í kom-po-nenta [][][][], která si udr-ºuje fro []\T1/lmr/m/n/12 Spolehlivost °e²í kom-po-nenta [][][][], která si udr-ºuje fro
ntu rámc·, ntu rámc·,
[] []
[35] [34]
Overfull \hbox (6.44025pt too wide) in paragraph at lines 976--977 Overfull \hbox (6.44025pt too wide) in paragraph at lines 976--977
[][][][][][][][][][][][][] \T1/lmr/m/n/12 a [][][][][][][][][][][][][][][][]. K [][][][][][][][][][][][][] \T1/lmr/m/n/12 a [][][][][][][][][][][][][][][][]. K
aºdý aºdý
[] []
<graphics/zone_server_architecture.pdf, id=452, 453.61469pt x 298.23419pt> [35]
<graphics/zone_server_architecture.pdf, id=456, 453.61469pt x 298.23419pt>
File: graphics/zone_server_architecture.pdf Graphic file (type pdf) File: graphics/zone_server_architecture.pdf Graphic file (type pdf)
<use graphics/zone_server_architecture.pdf> <use graphics/zone_server_architecture.pdf>
Package pdftex.def Info: graphics/zone_server_architecture.pdf used on input l Package pdftex.def Info: graphics/zone_server_architecture.pdf used on input l
ine 984. ine 984.
(pdftex.def) Requested size: 409.50119pt x 269.24106pt. (pdftex.def) Requested size: 409.50119pt x 269.24106pt.
[36]
<graphics/lobby_ui.png, id=457, 1929.2075pt x 1209.51875pt> <graphics/lobby_ui.png, id=457, 1929.2075pt x 1209.51875pt>
File: graphics/lobby_ui.png Graphic file (type png) File: graphics/lobby_ui.png Graphic file (type png)
<use graphics/lobby_ui.png> <use graphics/lobby_ui.png>
Package pdftex.def Info: graphics/lobby_ui.png used on input line 1002. Package pdftex.def Info: graphics/lobby_ui.png used on input line 1002.
(pdftex.def) Requested size: 409.50119pt x 256.73788pt. (pdftex.def) Requested size: 409.50119pt x 256.73788pt.
<graphics/ui_showcase.png, id=458, 2566.58875pt x 1412.27625pt> [36 <./graphics/zone_server_architecture.pdf>]
<graphics/ui_showcase.png, id=478, 2566.58875pt x 1412.27625pt>
File: graphics/ui_showcase.png Graphic file (type png) File: graphics/ui_showcase.png Graphic file (type png)
<use graphics/ui_showcase.png> <use graphics/ui_showcase.png>
Package pdftex.def Info: graphics/ui_showcase.png used on input line 1009. Package pdftex.def Info: graphics/ui_showcase.png used on input line 1009.
(pdftex.def) Requested size: 409.50119pt x 225.32233pt. (pdftex.def) Requested size: 409.50119pt x 225.32233pt.
[37 <./graphics/zone_server_architecture.pdf>] [38 <./graphics/lobby_ui.png> < [37 <./graphics/lobby_ui.png>] [38 <./graphics/ui_showcase.png>]
./graphics/ui_showcase.png>] [39]
<graphics/grafana.png, id=493, 2813.51125pt x 913.4125pt> <graphics/grafana.png, id=493, 2813.51125pt x 913.4125pt>
File: graphics/grafana.png Graphic file (type png) File: graphics/grafana.png Graphic file (type png)
<use graphics/grafana.png> <use graphics/grafana.png>
Package pdftex.def Info: graphics/grafana.png used on input line 1042. Package pdftex.def Info: graphics/grafana.png used on input line 1042.
(pdftex.def) Requested size: 409.50119pt x 132.9362pt. (pdftex.def) Requested size: 409.50119pt x 132.9362pt.
<graphics/300playerstrace.png, id=495, 1348.03625pt x 397.485pt> [39 <./graphics/grafana.png>]
<graphics/300playerstrace.png, id=501, 1348.03625pt x 397.485pt>
File: graphics/300playerstrace.png Graphic file (type png) File: graphics/300playerstrace.png Graphic file (type png)
<use graphics/300playerstrace.png> <use graphics/300playerstrace.png>
Package pdftex.def Info: graphics/300playerstrace.png used on input line 1056. Package pdftex.def Info: graphics/300playerstrace.png used on input line 1056.
(pdftex.def) Requested size: 409.50119pt x 120.74449pt. (pdftex.def) Requested size: 409.50119pt x 120.74449pt.
[40 <./graphics/grafana.png>] [40 <./graphics/300playerstrace.png>]
<graphics/latencycomparison.pdf, id=504, 462.52798pt x 346.89601pt> <graphics/latencycomparison.pdf, id=509, 462.52798pt x 346.89601pt>
File: graphics/latencycomparison.pdf Graphic file (type pdf) File: graphics/latencycomparison.pdf Graphic file (type pdf)
<use graphics/latencycomparison.pdf> <use graphics/latencycomparison.pdf>
Package pdftex.def Info: graphics/latencycomparison.pdf used on input line 110 Package pdftex.def Info: graphics/latencycomparison.pdf used on input line 110
0. 0.
(pdftex.def) Requested size: 327.60219pt x 245.71564pt. (pdftex.def) Requested size: 327.60219pt x 245.71564pt.
<graphics/integrationcomparison.pdf, id=506, 462.52798pt x 346.89601pt> <graphics/integrationcomparison.pdf, id=511, 462.52798pt x 346.89601pt>
File: graphics/integrationcomparison.pdf Graphic file (type pdf) File: graphics/integrationcomparison.pdf Graphic file (type pdf)
<use graphics/integrationcomparison.pdf> <use graphics/integrationcomparison.pdf>
Package pdftex.def Info: graphics/integrationcomparison.pdf used on input line Package pdftex.def Info: graphics/integrationcomparison.pdf used on input line
1110. 1110.
(pdftex.def) Requested size: 327.60219pt x 245.71564pt. (pdftex.def) Requested size: 327.60219pt x 245.71564pt.
[41 <./graphics/300playerstrace.png>] [42 <./graphics/latencycomparison.pdf> < [41 <./graphics/latencycomparison.pdf>]
./graphics/integrationcomparison.pdf>] <graphics/playerbenchmark.png, id=570, 1926.19624pt x 1221.56375pt>
<graphics/playerbenchmark.png, id=613, 1926.19624pt x 1221.56375pt>
File: graphics/playerbenchmark.png Graphic file (type png) File: graphics/playerbenchmark.png Graphic file (type png)
<use graphics/playerbenchmark.png> <use graphics/playerbenchmark.png>
Package pdftex.def Info: graphics/playerbenchmark.png used on input line 1122. Package pdftex.def Info: graphics/playerbenchmark.png used on input line 1122.
@@ -1684,21 +1689,21 @@ File: graphics/300playerstrace.png Graphic file (type png)
Package pdftex.def Info: graphics/300playerstrace.png used on input line 1133. Package pdftex.def Info: graphics/300playerstrace.png used on input line 1133.
(pdftex.def) Requested size: 409.50119pt x 120.74449pt. (pdftex.def) Requested size: 409.50119pt x 120.74449pt.
[43 <./graphics/playerbenchmark.png>] [42 <./graphics/integrationcomparison.pdf> <./graphics/playerbenchmark.png>]
<graphics/ecs_optimization_tracy_01.png, id=624, 1707.37875pt x 472.76625pt> <graphics/ecs_optimization_tracy_01.png, id=622, 1707.37875pt x 472.76625pt>
File: graphics/ecs_optimization_tracy_01.png Graphic file (type png) File: graphics/ecs_optimization_tracy_01.png Graphic file (type png)
<use graphics/ecs_optimization_tracy_01.png> <use graphics/ecs_optimization_tracy_01.png>
Package pdftex.def Info: graphics/ecs_optimization_tracy_01.png used on input Package pdftex.def Info: graphics/ecs_optimization_tracy_01.png used on input
line 1148. line 1148.
(pdftex.def) Requested size: 409.50119pt x 113.38686pt. (pdftex.def) Requested size: 409.50119pt x 113.38686pt.
<graphics/ecs_optimization_tracy_02.png, id=625, 1196.47pt x 583.17876pt> <graphics/ecs_optimization_tracy_02.png, id=623, 1196.47pt x 583.17876pt>
File: graphics/ecs_optimization_tracy_02.png Graphic file (type png) File: graphics/ecs_optimization_tracy_02.png Graphic file (type png)
<use graphics/ecs_optimization_tracy_02.png> <use graphics/ecs_optimization_tracy_02.png>
Package pdftex.def Info: graphics/ecs_optimization_tracy_02.png used on input Package pdftex.def Info: graphics/ecs_optimization_tracy_02.png used on input
line 1155. line 1155.
(pdftex.def) Requested size: 409.50119pt x 199.59514pt. (pdftex.def) Requested size: 409.50119pt x 199.59514pt.
[44 <./graphics/ecs_optimization_tracy_01.png> <./graphics/ecs_optimization_tr [43 <./graphics/ecs_optimization_tracy_01.png>] [44 <./graphics/ecs_optimizati
acy_02.png>] on_tracy_02.png>]
Underfull \hbox (badness 10000) in paragraph at lines 1194--1194 Underfull \hbox (badness 10000) in paragraph at lines 1194--1194
[]|\T1/lmr/m/n/12 Název []|\T1/lmr/m/n/12 Název
[] []
@@ -1713,13 +1718,13 @@ Underfull \hbox (badness 10000) in paragraph at lines 1200--1200
[]|\T1/lmr/m/n/12 Hashovací []|\T1/lmr/m/n/12 Hashovací
[] []
[45] [46] [45]
<graphics/peer_to_peer.pdf, id=646, 433.62pt x 361.35pt> <graphics/peer_to_peer.pdf, id=646, 433.62pt x 361.35pt>
File: graphics/peer_to_peer.pdf Graphic file (type pdf) File: graphics/peer_to_peer.pdf Graphic file (type pdf)
<use graphics/peer_to_peer.pdf> <use graphics/peer_to_peer.pdf>
Package pdftex.def Info: graphics/peer_to_peer.pdf used on input line 1228. Package pdftex.def Info: graphics/peer_to_peer.pdf used on input line 1228.
(pdftex.def) Requested size: 204.7506pt x 170.6285pt. (pdftex.def) Requested size: 204.7506pt x 170.6285pt.
[47 <./graphics/peer_to_peer.pdf>] [48 [46] [47 <./graphics/peer_to_peer.pdf>] [48
] [49 ] [49
@@ -1776,9 +1781,6 @@ L3 programming layer <2026-01-19>
LaTeX Warning: There were undefined references. LaTeX Warning: There were undefined references.
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
Package biblatex Warning: Please (re)run Biber on the file: Package biblatex Warning: Please (re)run Biber on the file:
(biblatex) kidiplom (biblatex) kidiplom
(biblatex) and rerun LaTeX afterwards. (biblatex) and rerun LaTeX afterwards.
@@ -1788,11 +1790,11 @@ Package logreq Info: Writing requests to 'kidiplom.run.xml'.
) )
Here is how much of TeX's memory you used: Here is how much of TeX's memory you used:
33962 strings out of 469481 33968 strings out of 469481
640452 string characters out of 5469631 640672 string characters out of 5469631
1776455 words of memory out of 5000000 1772587 words of memory out of 5000000
61865 multiletter control sequences out of 15000+600000 61870 multiletter control sequences out of 15000+600000
703044 words of font info for 102 fonts, out of 8000000 for 9000 706039 words of font info for 103 fonts, out of 8000000 for 9000
24 hyphenation exceptions out of 8191 24 hyphenation exceptions out of 8191
110i,11n,112p,2637b,4669s stack positions out of 10000i,1000n,20000p,200000b,200000s 110i,11n,112p,2637b,4669s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/share/texmf-dist/fonts/type1/public/lm/lmbx10.pfb></usr/share/texmf-dis </usr/share/texmf-dist/fonts/type1/public/lm/lmbx10.pfb></usr/share/texmf-dis
@@ -1804,10 +1806,10 @@ share/texmf-dist/fonts/type1/public/lm/lmr8.pfb></usr/share/texmf-dist/fonts/ty
pe1/public/lm/lmri12.pfb></usr/share/texmf-dist/fonts/type1/public/lm/lmsy10.pf pe1/public/lm/lmri12.pfb></usr/share/texmf-dist/fonts/type1/public/lm/lmsy10.pf
b></usr/share/texmf-dist/fonts/type1/urw/courier/ucrb8a.pfb></usr/share/texmf-d b></usr/share/texmf-dist/fonts/type1/urw/courier/ucrb8a.pfb></usr/share/texmf-d
ist/fonts/type1/urw/courier/ucrr8a.pfb> ist/fonts/type1/urw/courier/ucrr8a.pfb>
Output written on kidiplom.pdf (52 pages, 1160573 bytes). Output written on kidiplom.pdf (52 pages, 1172626 bytes).
PDF statistics: PDF statistics:
1027 PDF objects out of 1200 (max. 8388607) 1031 PDF objects out of 1200 (max. 8388607)
776 compressed objects within 8 object streams 778 compressed objects within 8 object streams
178 named destinations out of 1000 (max. 500000) 179 named destinations out of 1000 (max. 500000)
646 words of extra memory for PDF output out of 10000 (max. 10000000) 651 words of extra memory for PDF output out of 10000 (max. 10000000)
+2 -2
View File
@@ -1,6 +1,6 @@
\babel@toc {czech}{}\relax \babel@toc {czech}{}\relax
\contentsline {table}{\numberline {1}{\ignorespaces Porovnání serializátorů}}{45}{table.1}% \contentsline {table}{\numberline {1}{\ignorespaces Porovnání serializátorů}}{44}{table.1}%
\contentsline {table}{\numberline {2}{\ignorespaces Porovnání algoritmů}}{46}{table.2}% \contentsline {table}{\numberline {2}{\ignorespaces Porovnání algoritmů}}{45}{table.2}%
\babel@toc {czech}{}\relax \babel@toc {czech}{}\relax
\babel@toc {czech}{}\relax \babel@toc {czech}{}\relax
\babel@toc {english}{}\relax \babel@toc {english}{}\relax
BIN
View File
Binary file not shown.
Binary file not shown.
+59 -59
View File
@@ -574,17 +574,8 @@ Všimněme si teď různých typů paketů: Initial, Handshake, 0-RTT a 1-RTT. L
\section{Hra} \section{Hra}
V této kapitole představíme hru, kterou jsem vyvinuli pro demonstraci různých technik a jejich měření. Ve hře má každý hráč svou postavu, se kterou může volně pohybovat ve 3D prostoru. Hra simuluje na postavách hráčů realistickou fyziku. Pokud se do hry připojí více hráčů, tak se navzájem vidí. Každý hráč spustí program klienta, který zobrazuje stav hry a postavy hráčů v 3D prostoru. V další kapitole porovnáme plynulost pohybu a rychlost odezvy, které jsou pro hratelnost důležité. V této kapitole představíme hru, kterou jsem vyvinuli pro demonstraci různých technik a jejich měření. Ve hře má každý hráč svou postavu, se kterou může volně pohybovat ve 3D prostoru. Hra simuluje na postavách hráčů realistickou fyziku. Pokud se do hry připojí více hráčů, vidí se navzájem. Každý hráč spustí program klienta, který zobrazuje stav hry a postavy hráčů v 3D prostoru. V této kapitole popíšeme obecnou architekturu hry a našeho enginu. V další kapitole rozšíříme a upravíme tento model pro hru více hráčů. Vytvoříme tak distribuovaný sysm.
V první části popíšeme architekturu hry a našeho enginu. Následně rozšíříme a jinak upravíme tento model pro hru více hráčů. Vytvoříme tak distribuovaný systém.
Naše první implementace využívá model klient-server, kde máme dva různé programy: server a klient. Podrobně popíšeme, které komponenty jsme přidali, které pouze přesunuli do programu serveru a které naopak ponechali v programu klienta.
Mezi hlavní prvky patří náš vlastní komunikační protokol transportní vrstvy: \uv{QUICr}. Je to obousměrný protokol pro posílání zpráv jako n-tic bytů, který se inspiruje protokolem QUIC, ale upravuje ho pro lepší využití pro hry. Náš protokol lépe zachycuje závislosti mezi zprávami a umožňuje i posílat zprávy nespolehlivě. Díky tomu se úplně zbavuje ahead-of-line blokování.
Zjistili jsme, že důležitým vylepšením je vlastní serializace primitivních zpráv. Pokud například obsahuje pouze seznam pozic, může být vlastní serializace rozdíl mezi hratelnou a nehratelnou odezvou. Popíšeme, jak jsme rychlost měřili a jaké metody jsme pro vlastní serializaci použili.
Nakonec představíme i architekturu peer-to-peer, kdy umožníme, aby v systému bylo více spolupracujících serverů, které si mezi sebou budou rozdělovat práci. Zároveň porovnáme i případ, kdy není žádný autoritativní server a hráči se mezi sebou synchronizují samovolně.
\subsection{Engine} \subsection{Engine}
@@ -599,7 +590,7 @@ Pro hru jsme vyvinuli vlastní herní engine tak, abychom mohli celý systém do
% Vstup od hráče -> akce % Vstup od hráče -> akce
% Co je herní stav, jak probíhá kolo? % Co je herní stav, jak probíhá kolo?
Mezi hlavní komponenty patří \uv{stav} hry a \uv{řídící logika}. Stav obsahuje množinu entit, které jsou ve hře a jejich vlasnosti a atributy. Entity jsou objekty v herním světě, jako postava hráče, nepřátele nebo interaktivní prvky jako truhla s pokladem. Entita má přiřazené vlastnosti, které ji dávají stav. Entita nepřítele může mít vlastnost "množství životů" a truhla vlastnost "poklad", která definuje, co je v truhle obsaženo. Stavu hry se někdy říká pouze \uv{svět}. Mezi hlavní komponenty patří \uv{stav} hry a \uv{řídící logika}. Stav obsahuje množinu entit, které jsou ve hře, jejich vlasnosti a atributy. Entity jsou objekty v herním světě, jako postava hráče, nepřátele nebo interaktivní prvky, například truhla s pokladem. Entita má přiřazené vlastnosti, které jí dávají stav. Entita nepřítele může mít vlastnost \uv{množství životů} a truhla vlastnost \uv{poklad}, která definuje, co je v truhle obsaženo. Stavu hry se někdy říká pouze \uv{svět}.
@@ -608,10 +599,10 @@ Mezi hlavní komponenty patří \uv{stav} hry a \uv{řídící logika}. Stav obs
% Stav hry reprezentujeme kompletně ve třídě \inlcpp{World}. Ta obsahuje registr z knihovny Entt. Řídící logika je ve třídě \inlcpp{WorldController}. Obsahuje smyčku, která v každé iteraci posbírá vstupy od hráče, převede je na akce a aplikuje je společně s další definovanout logikou. Například v naší hře má vstup: stisknutí klávesy W, definovaný příkaz: \uv{posuň dopředu}, která změní vektor zrychlení hráče. Dalšími prvky, které mění změnu stavu je například fyzický engine, který upravuje zrychlení podle nárazů a nebo vlivů sil, například gravitace. % Stav hry reprezentujeme kompletně ve třídě \inlcpp{World}. Ta obsahuje registr z knihovny Entt. Řídící logika je ve třídě \inlcpp{WorldController}. Obsahuje smyčku, která v každé iteraci posbírá vstupy od hráče, převede je na akce a aplikuje je společně s další definovanout logikou. Například v naší hře má vstup: stisknutí klávesy W, definovaný příkaz: \uv{posuň dopředu}, která změní vektor zrychlení hráče. Dalšími prvky, které mění změnu stavu je například fyzický engine, který upravuje zrychlení podle nárazů a nebo vlivů sil, například gravitace.
Druhá část je řídící logika, která iterativně mění stav hry. Tato změna může být pouze na základě stavu světa, například posune objekt, který má nenulový vektor zrychlení. Mimo to může řídící logika reagovat na údalosti. Například stisk tlačítka W je událost, který vyvolá změnu vektoru zrychlení hráče, který tlačítko stiskl. V důsledku toho se postava hráče pohne. Druhou část tvoří řídící logika, která iterativně mění stav hry. Tato změna může být pouze na základě stavu světa, například posun objektu, který má nenulový vektor zrychlení. Mimo to může řídící logika reagovat na údalosti. Například stisk tlačítka W je událost, který vyvolá změnu vektoru zrychlení hráče, který tlačítko stiskl. V důsledku toho se postava hráče pohne.
Každá iterace řídící logiky trvá přibližně stejně dlouho, většinou 1/60 sekundy nebo 1/24 sekundy. Vyšší frekvence znamená nižší odezvu a lepší plynulost. Nižší frekvence znamená menší výpočetní náročnost. Pro pomalejší hry bez rychlých akčních pasáží se využívá frekvence 24Hz a u kompetentních her i 120Hz Každá iterace řídící logiky trvá přibližně stejně dlouho, většinou 1/60 sekundy nebo 1/24 sekundy. Vyšší frekvence znamená nižší odezvu a lepší plynulost. Nižší frekvence znamená menší výpočetní náročnost. Pro pomalejší hry bez rychlých akčních pasáží se využívá frekvence 24Hz a u kompetetivních her i 120Hz
\footnote{Článek od Riot Games ukazuje, jak důležitá je odezva u kompetetivních her. U profesionálních hráčů je poznat i rozdíl mezi 120Hz a 240Hz. https://www.riotgames.com/en/news/peeking-valorants-netcode}. \footnote{Článek\cite{peekingvalorant} od Riot Games ukazuje, jak důležitá je odezva u kompetetivních her. U profesionálních hráčů je poznat i rozdíl mezi 120Hz a 240Hz.}.
\begin{figure} \begin{figure}
\begin{center} \begin{center}
@@ -623,25 +614,25 @@ Každá iterace řídící logiky trvá přibližně stejně dlouho, většinou
\subsubsection{Fyzický engine} \subsubsection{Fyzický engine}
Hra je 3D a chtěli jsme simulovat otevřený svět, ve kterém platí zákony fyziky. Pro simulaci jsme využili existující fyzický engine \uv{Jolt} a zabalili ho do modulu. Jolt je populární projekt, který je využíván například v Horizon: Forbidden West nebo Death Stranding 2. Hra je ve 3D a cílem bylo simulovat otevřený svět, ve kterém platí zákony fyziky. Pro simulaci jsme využili existující fyzický engine \uv{Jolt} a zabalili jej do modulu. Jolt je populární projekt, který je využíván například v Horizon: Forbidden West nebo Death Stranding 2.
Pro použití jsme vytvořili instanci fyzického světa, do kterého naskládáme objekty a jejich vlastnosti, jako hmotnost a tvar. Zavoláním metody pro aktualizaci engine posune stav entit (zrychlení a pozice). Vše jsme obalili do \inlcpp{JoltPhysicsWorld}. Simulace probíhá nad instancí fyzického světa, do kterého naskládáme objekty a jejich vlastnosti, jako hmotnost a tvar. Zavoláním metody pro aktualizaci engine posune stav entit (zrychlení a pozice). Vše jsme zapouzdřili do \inlcpp{JoltPhysicsWorld}.
Jolt umí využít více vláken procesoru a podporuje \uv{rollback}, který umožňuje vracet stav v historii simulace dozadu. Je to důležitá věc pro hry více hráčů a obecně distribuovaných systémů, pro řešení desynchronizace. Jolt umí využít více vláken procesoru a podporuje \uv{rollback}, který umožňuje vrátit simulaci do některého z předchozích stavů. To je důležitá věc pro hry více hráčů a obecně distribuovaných systémů pro řešení desynchronizace.
\subsubsection{Vykreslování} \subsubsection{Vykreslování}
K vykreslování jsme použili náš vlastní engine. Pro vykreslení 3D objektu je potřeba popsat jeho povrch jako množinu polygonů. Této množině se říká \uv{mesh}. Vykreslení jednoho snímku lze v enginu popsat jako graf operací. Běžně bude obsahovat operaci, která seznam mesh vykreslí do obrázku. Tento celý proces lze shrnout jednou operací, protože o celý algoritmus a logiku se stará grafická karta. Vývojář jen popisuje mesh a například jakou má mít barvu apod. K vykreslování jsme použili náš vlastní engine. Pro vykreslení 3D objektu je potřeba popsat jeho povrch jako množinu polygonů. Této množině se říká \uv{mesh}. Vykreslení jednoho snímku lze v enginu popsat jako graf operací. Běžně bude obsahovat operaci, která seznam mesh vykreslí do obrázku. Tento celý proces lze shrnout jednou operací, protože o celý algoritmus a logiku se stará grafická karta. Vývojář jen popisuje mesh a jeho vlastnosti, například jakou má mít barvu apod.
Mezi operacemi v grafu definujeme závislosti. Díky tomu můžeme definovat operaci, která vykreslí 3D mesh a druhou operaci, která je na ni závislá, a která přes obrázek vykreslí uživatelské rozhraní. Mezi operacemi v grafu definujeme závislosti. Díky tomu můžeme definovat operaci, která vykreslí 3D mesh a druhou operaci, která je na ní závislá a přes obrázek vykreslí uživatelské rozhraní.
V našem případě máme právě operaci pro vykreslení statických objektů, jako povrchu, po kterém se hráči pohybují apod. Druhá operace vykreslí samotné hráče a jiné dynamické objekty. Poslední operaci vykreslí uživatelské rozhraní obsahující různé nástroje pro různé ladění programu. V našem případě máme právě k dispozici operaci pro vykreslení statických objektů, jako například povrchu, po kterém se hráči pohybují. Druhá operace vykreslí samotné hráče a jiné dynamické objekty. Poslední operace vykreslí uživatelské rozhraní obsahující různé nástroje pro libovolné ladění programu.
\subsubsection{Entity-Component-System} \subsubsection{Entity-Component-System}
V programu využíváme architekturu entity-component-system, zkráceně ECS, která je pro hry běžná. Entity jsme popsali výše. Ke konkrétním entitám vážeme instance komponent, které entitě dají stav. Většinou je komponenta přiřazena právě jedné entitě. Poslední částí jsou systémy, které reprezentují řídící logiku. Systém je definován funkcí, která prochází entity, které splňují definovanou podmínku a mění stav její komponent. Tato podmínka většinou pouze omezuje na entity, které mají přiřazené komponenty pro určité typy. Systém může například simulovat fyziku, a to přičítáním zrychlení k pozici. K tomu definuje podmínku, která procházenou množinu omezí na entity, které mají potřebné komponenty. Těmi jsou komponenta transformace a komponenta zrychlení. V programu využíváme pro hry běžnou architekturu entity-component-system, zkráceně ECS. Entity jsme již popsali výše. Ke konkrétním entitám vážeme instance komponent, které entitě dají stav. Většinou je komponenta přiřazena právě jedné entitě. Poslední částí jsou systémy, které reprezentují řídící logiku. Systém je definován funkcí, která prochází entity, které splňují definovanou podmínku a mění stav jejich komponent. Tato podmínka se většinou omezuje na entity, které mají přiřazené komponenty pro určité typy. Systém může například simulovat fyziku, a to přičítáním zrychlení k pozici. K tomu definuje podmínku, která procházenou množinu omezí na entity, které mají potřebné komponenty. Těmi jsou komponenta transformace a komponenta zrychlení.
Motivací této architektury je jednoduché skládání různých entit, které jsou pro rozmanité herní světy typické. Pomocí stromu dědičnosti bychom tyto různé scénáře hůře skládali. Další výhoda je zlepšení výkonu. Protože si engine může poskládat entity a jejich komponenty do paměti jak chce, může umístění optimalizovat pro definované systémy tak, aby iterování bylo co nejrychlejší. Tomuto se říká problém lokality. Motivací této architektury je jednoduché skládání různých entit, které jsou pro rozmanité herní světy typické. Pomocí stromu dědičnosti bychom tyto různé scénáře hůře skládali. Další výhodou je zlepšení výkonu. Protože si engine může poskládat entity a jejich komponenty do paměti jak chce, může umístění optimalizovat pro definované systémy tak, aby iterování bylo co nejrychlejší. Tomuto se říká problém lokality.
@@ -662,7 +653,7 @@ Motivací této architektury je jednoduché skládání různých entit, které
}); });
\end{kicode} \end{kicode}
Pro ECS využíváme knihovnu \uv{Entt}, která usnadňuje definici entit, přiřazování komponent a definici systémů. Entita je v této knihovně pouze unikátně identifikační číslo a komponenta je libovolný typ. V registru pak můžeme vytvářet \uv{pohledy} na n-tici typů komponent, které jsou seznam právě všech entit v registru, které všechny tyto komponenty mají. Ten můžeme procházet a libovolně měnit atributy komponent. Příklad použití vidíme v \ref{code:entt}, kde nejprve vytvoříme registr do kterého přidáme novou entity a přiřadíme ji komponentu typu Transform. Nakonec definujeme pohled na všechny entity, které mají komponentu obou typů: Transform i CharacterBody. Před tento pohled iterujeme a v každé iteraci kopírujeme. Představíme komponenty, které jsme pro hru definovali a proč: Pro ECS využíváme knihovnu \uv{Entt}, která usnadňuje definici entit, přiřazování komponent a definici systémů. Entita je v této knihovně pouze unikátní identifikační číslo a komponenta je libovolný typ. V registru pak můžeme vytvářet \uv{pohledy} na n-tici typů komponent, které představují seznam právě všech entit v registru, které všechny tyto komponenty mají. Ten můžeme procházet a libovolně měnit atributy komponent. Příklad použití vidíme ve zdrojovém kódu \ref{code:entt}, kde nejprve vytvoříme registr do kterého přidáme novou entitu a přiřadíme jí komponentu typu Transform. Nakonec definujeme pohled na všechny entity, které mají komponentu obou typů: Transform i CharacterBody. Přes tento pohled iterujeme a v každé iteraci kopírujeme. Představíme komponenty, které jsme pro hru definovali a proč:
\begin{description} \begin{description}
@@ -670,7 +661,7 @@ Pro ECS využíváme knihovnu \uv{Entt}, která usnadňuje definici entit, při
Obsahuje transformační matici. Entity, které chceme zobrazit ve světě, tuto komponentu potřebují. Příkladem entity, která ji mít nebude, je zpráva v chatu. Obsahuje transformační matici. Entity, které chceme zobrazit ve světě, tuto komponentu potřebují. Příkladem entity, která ji mít nebude, je zpráva v chatu.
\item[{Mesh}] \hfill \\ \item[{Mesh}] \hfill \\
Obsahuje mesh, který má hra využít pro vykreslení entity. Mesh je n-tici bodů, které dohromady dávají 3D povrch objektu. Komponenta neobsahuje body, ale pouze odkaz na buffer, ve kterém je najdeme a kde. Systém, který entity vykresluje si vytvoří pohled na Mesh a Transform, protože je potřeba vědět kam entitu vykreslit. Obsahuje mesh, který má hra využít pro vykreslení entity. Mesh je n-tice bodů, které dohromady dávají 3D povrch objektu. Komponenta neobsahuje body, ale pouze odkaz na buffer, ve kterém jsou uloženy a informaci o jejich umístění. Systém, který entity vykresluje si vytvoří pohled na Mesh a Transform, protože je potřeba vědět kam entitu vykreslit.
\item[{Rigidbody}] \hfill \\ \item[{Rigidbody}] \hfill \\
Slouží pro fyzikální informace o entitě, jako hmotnost a zrychlení, které na entitu budeme aplikovat. Systém pro tuto komponentu bude ve fyzickém enginu. Slouží pro fyzikální informace o entitě, jako hmotnost a zrychlení, které na entitu budeme aplikovat. Systém pro tuto komponentu bude ve fyzickém enginu.
@@ -680,9 +671,9 @@ Pro ECS využíváme knihovnu \uv{Entt}, která usnadňuje definici entit, při
\subsubsection{ImGui} \subsubsection{ImGui}
Některé metriky jsme chtěli zobrazit přímo v klientovi pro hru. Jsou to například příchozí a odchozí množství dat klienta. Tyto data neukládáme nikam do databáze a musíme si je spravovat lokálně. Proto jsme v klientovi potřebovali zobrazit základní uživatelské rozhraní. Zvolili jsme knihovnu ImGui a ImPlot, které se integrují přímo do vykreslovacího enginu. Pro knihovnu jsme přidali jednu novou úlohu do vykreslovacího grafu. Některé metriky jsme chtěli zobrazit přímo v klientovi pro hru. Jsou to například příchozí a odchozí množství dat klienta. Tyto data neukládáme do databáze, ale musíme si je spravovat lokálně. Proto jsme v klientovi potřebovali zobrazit základní uživatelské rozhraní. Zvolili jsme knihovnu ImGui a ImPlot, které se integrují přímo do vykreslovacího enginu. Pro knihovnu jsme přidali jednu novou úlohu do vykreslovacího grafu.
S knihovnou se pracuje procedurálně, nikoliv objektově. Každý snímek je třeba definovat celé rozhraní znova. Pro definici voláme různé funkce, kde každá definuje v rozhraní některý z možných prvků. Například funkce \inlcpp{InputText} zobrazí vstup pro text. Důležitá je funkce \inlcpp{Begin("Název okna")}, která zobrazí okno, do kterého můžeme vložit další prvky, jako texty, textové vstupy, nebo tlačítka. Tento přístup je pro herní enginy a podobné kreativní aplikace ideální, protože umožňuje velmi snadno a rychle dělat dynamické uživatelské rozhraní. S knihovnou se pracuje procedurálně, nikoliv objektově. Pro každý snímek je třeba definovat celé uživatelské rozhraní znovu. Pro definici voláme různé funkce, kde každá definuje v rozhraní některý z možných prvků. Například funkce \inlcpp{InputText} zobrazí vstup pro text. Důležitá je funkce \inlcpp{Begin("Název okna")}, která zobrazí okno, do kterého můžeme vložit další prvky, jako texty, textové vstupy, nebo tlačítka. Tento přístup je pro herní enginy a podobné kreativní aplikace ideální, protože umožňuje velmi snadno a rychle dělat dynamické uživatelské rozhraní.
@@ -701,13 +692,13 @@ S knihovnou se pracuje procedurálně, nikoliv objektově. Každý snímek je t
V předchozí části jsme představili základní implementaci hry pro jednoho hráče. V této části ukážeme, jak jsme hru rozšířili na síťový systém a umožnili hru více hráčů. To znamená, že více hráčů se může připojit do stejné instance hry a navzájem spolu interagovat. V předchozí části jsme představili základní implementaci hry pro jednoho hráče. V této části ukážeme, jak jsme hru rozšířili na síťový systém a umožnili hru více hráčů. To znamená, že více hráčů se může připojit do stejné instance hry a navzájem spolu interagovat.
Jako první jsme implementovali model klient-server. Diagram systému vidíme na obrázku \ref{fig:multi_player_game}. Stav hry řídí autoritativní server, který ho replikuje klientům posíláním snapshotů. Klient zobrazuje stav hry hráči, stejně jako v případě hry jednoho hráče. Autorita serveru zjednodušuje konzistenci a detekci podvádění. Klienti na server neposílají svůj stav, ale pouze akce, které chtějí provést. Příkladem může být akce pohybu dopředu, kterou vyvolal hráč. Server má možnost akce odmítnout a libovolně interpretovat, protože konečné slovo má právě server. Server rozesílá klientům zprávy zvané snapshoty, které obsahují aktuální stav hry (např. pozice entit) a události pro jednorázové akce (např. událost o konci hry). Jako první jsme implementovali model klient-server. Diagram systému vidíme na obrázku \ref{fig:multi_player_game}. Stav hry řídí autoritativní server, který ho replikuje klientům posíláním snapshotů. Klient zobrazuje stav hry hráčovi, stejně jako v případě hry jednoho hráče. Autorita serveru zjednodušuje konzistenci a detekci podvádění. Klienti na server neposílají svůj stav, ale pouze akce, které chtějí provést. Příkladem může být akce pohybu dopředu, kterou vyvolal hráč. Server má možnost akce odmítnout a libovolně interpretovat, protože konečné slovo má právě server. Server rozesílá klientům zprávy zvané snapshoty, které obsahují aktuální stav hry (např. pozice entit) a události pro jednorázové akce (např. událost o konci hry).
Druhá varianta je model peer-to-peer. Ta je složitější z hlediska konzistence. Účastníci si mezi sebou posílají akce a každý si udržuje svůj stav, který ale nikomu nereplikuje. Každý se tak chová jako server v modelu klient-server. Je potřeba, aby každý účastník měl kompletní historii akcí všech ostatních v systému ve správném pořadí. Tomuto se říká \uv{event-sourcing}. V případě, že se historie liší, dochází k nekonzistenci. Druhá varianta je model peer-to-peer. Ta je složitější z hlediska konzistence. Účastníci si mezi sebou posílají akce a každý si udržuje svůj stav, který ale nikomu nereplikuje. Každý se tak chová jako server v modelu klient-server. Je potřeba, aby každý účastník měl kompletní historii akcí všech ostatních v systému ve správném pořadí. Tomuto se říká \uv{event-sourcing}. V případě, že se historie liší, dochází k nekonzistenci.
Druhá komplikace peer-to-peer je, že aplikace stejné akce na stejný stav musí mít vždy stejný výsledek. Pokud by dva procesy ve stejném stavu po aplikaci stejné akce na stav dospěli do jiného stavu, dochází k desynchronizaci. Problémové oblasti jsou generování pseudo-náhodných čísel a integrace. Výsledek integrace je často závislý na frekvenci. Například fyzický engine postupně integruje pozice entit podle derivace, která je reprezentována vektorem zrychlení. Každá integrace musí definovat, o jak velký časový krok se jedná (tzv. delta-time) a všichni účastníci se na něm musejí shodnout. Různé délky by rychle způsobily desynchronizaci. Zároveň všechny pseudonáhodné generátory musejí mít stejný počáteční seed. Je třeba si dát pozor na aritmetriku s plovoucí desetinou čárkou, která na různých platformách může dopadnout trochu jinak. I malé rozdíly se mohou rychle projevit. Druhá komplikace peer-to-peer je, že aplikace stejné akce na stejný stav musí mít vždy stejný výsledek. Pokud by dva procesy ve stejném stavu po aplikaci stejné akce dospěli do jiného stavu, dochází k desynchronizaci. Problémovou oblastí je generování pseudo-náhodných čísel a integrace. Výsledek integrace je často závislý na frekvenci. Například fyzický engine postupně integruje pozice entit podle derivace, která je reprezentována vektorem zrychlení. Každá integrace musí definovat, o jak velký časový krok se jedná (tzv. delta-time) a všichni účastníci se na něm musejí shodnout. Různé délky by rychle způsobily desynchronizaci. Zároveň všechny pseudonáhodné generátory musejí mít stejný počáteční seed. Je třeba si dát pozor na aritmetriku s plovoucí desetinou čárkou, která na různých platformách může dopadnout odlišně. I malé rozdíly se mohou rychle projevit.
Rozšířenou architekturu vidíme na obrázku \ref{fig:multi_player_game}. Hned si všimneme, že se svět rozdvojil na instanci na serveru a instanci na klientovi. Jsou to právě tyto dvě instance, které se snažíme posíláním zpráv synchronizovat. Řídící logiku jsme rozdělili na Server World Controller a Client World Controller. Všimněme si, že ovladač na klientovi ne nutně obsahuje systémy, které by měnili stav hry, ale pouze kopíruje to, co mu server poslal ve zprávě pro snapshot. Na druhou stranu posílá akce, které přečetl od hráče. Oba ovladače ale zapisují do své instance světa. Rozšířenou architekturu vidíme na obrázku \ref{fig:multi_player_game}. Hned si všimneme, že se svět rozdvojil na instanci na serveru a instanci na klientovi. Jsou to právě tyto dvě instance, které se snažíme posíláním zpráv synchronizovat. Řídící logiku jsme rozdělili na Server World Controller a Client World Controller. Všimněme si, že ovladač na klientovi nutně neobsahuje systémy, které by měnily stav hry, ale pouze kopíruje to, co mu server poslal ve zprávě pro snapshot. Naopak posílá akce, které přečetl od hráče. Oba ovladače ale zapisují do své instance světa.
\begin{figure} \begin{figure}
\begin{center} \begin{center}
@@ -720,9 +711,9 @@ Rozšířenou architekturu vidíme na obrázku \ref{fig:multi_player_game}. Hned
\subsection{Server} \subsection{Server}
Představíme, jak vypadá architektura pro server a komponenty, ze kterých se skládá. Stejně jako hra jednoho hráče si ukládá stav hry, tedy instanci \inlcpp{World}. Navíc pro hru více hráčů jsou komponenty \uv{replikátor}. Ten posílá snapshoty a replikuje tak stav na serveru. Může posílat i jednorázové události. Představíme, jak vypadá architektura pro server a komponenty, ze kterých se skládá. Stejně jako hra jednoho hráče si ukládá stav hry, tedy instanci \inlcpp{World}. Navíc pro hru více hráčů existuje komponenta \uv{replikátor}. Ta posílá snapshoty a replikuje tak stav na serveru. Může posílat i jednorázové události.
Replikátor pracuje pouze s entitami a komponentami. Proto můžeme snapshot zjednoduššit na seznam entit s komponentami. Dále bude obsahovat seznam entit, které jsou nové a které naopak už mají zmizet. Stará se jen o to, jak tento stav synchronizovat pomocí posílání zpráv. Replikátor pracuje pouze s entitami a komponentami. Proto můžeme snapshot zjednoduššit na seznam entit s komponentami. Dále bude obsahovat seznam entit, které jsou nové, a seznam entit, které naopak už mají zmizet. Stará se jen o to, jak tento stav synchronizovat pomocí posílání zpráv.
Různé entity na serveru jsou pro některé hráče jinak důležité. Například ty, které jsou daleko, nemusíme synchronizovat, protože po vykreslení by nebyly vidět. Komponenta, která se o to stará je \uv{manažer zájmu}. Různé entity na serveru jsou pro některé hráče jinak důležité. Například ty, které jsou daleko, nemusíme synchronizovat, protože po vykreslení by nebyly vidět. Komponenta, která se o to stará je \uv{manažer zájmu}.
@@ -732,7 +723,7 @@ Obě tyto komponenty, společně se stavem a řídící logikou, jsou ve tříd
Komponenta, která spravuje a udržuje spojení s klienty hráčů, se nazývá \uv{registr klientů}. Slouží jako sifon pro všechny zprávy, které klienti odesílají. Zároveň z ní lze zjistit kdo se právě připojil a kdo odpojil. K tomu slouží metody: \inlcpp{popDisconnectedPlayers} a \inlcpp{popConnectedPlayers}. Udržuje seznam nových připojení od posledního zavolání \inlcpp{popConnectedPlayers}. Komponenta, která spravuje a udržuje spojení s klienty hráčů, se nazývá \uv{registr klientů}. Slouží jako sifon pro všechny zprávy, které klienti odesílají. Zároveň z ní lze zjistit kdo se právě připojil a kdo odpojil. K tomu slouží metody: \inlcpp{popDisconnectedPlayers} a \inlcpp{popConnectedPlayers}. Udržuje seznam nových připojení od posledního zavolání \inlcpp{popConnectedPlayers}.
Třída si u každého klienta hlídá počet po sobě jdoucích selhání. Jakmile počet překročí určitou hranici, např. 5 chyb, relaci s klientem ukončí. Tato komponenty skrývá samotné připojení s klientem a zbytek systému tak odpojení a připojení nemusí řešit. Pro získání seznamu existuje metoda \inlcpp{getClients}. Třída si u každého klienta hlídá počet po sobě jdoucích selhání. Jakmile počet překročí určitou hranici, např. 5 chyb, relaci s klientem ukončí. Tato komponenta skrývá samotné připojení s klientem a zbytek systému tak odpojení a připojení nemusí řešit. Pro získání seznamu existuje metoda \inlcpp{getClients}.
\subsubsection{Server Replikátoru} \subsubsection{Server Replikátoru}
@@ -740,9 +731,9 @@ Komponenta, která se snaží synchronizovat stav klientů s lokálním stavem n
\subsubsection{Správa zájmů} \subsubsection{Správa zájmů}
Komponenta, která řeší důležitost entit pro jednotlivé hráče, je \uv{manažer zájmu}. Důležitost definujeme pro každou dvojici klienta a entity. Manažer zájmu podle definované logiky, například na základě vzdálenosti, určí důležitost entity pro klienta. V základní verzi jsme měli pouze dvě hodnoty: důležitá a nedůležitá. Synchronizovali jsme pouze důležité. Replikátor se dotazuje manažera zájmu v moment, kdy klientovi chce stav synchronizovat. Komponenta, která řeší důležitost entit pro jednotlivé hráče, je \uv{manažer zájmu}. Důležitost definujeme pro každou dvojici klienta a entity. Manažer zájmu podle definované logiky, například na základě vzdálenosti, určí důležitost entity pro klienta. V základní verzi jsme měli pouze dvě hodnoty: důležitá a nedůležitá. Synchronizovali jsme pouze důležité. Replikátor se dotazuje manažera zájmu v okamžiku, kdy chce klientovi synchronizovat jeho stav.
Dotazu na všechny body, které jsou dostatečně blízko od konkrétního bodu, se říká `range-query`. Datové struktury které tuto operaci akcelerují jsou například fixní mřížka, dynamická mřížka nebo quad-tree. Dotazu na všechny body, které jsou dostatečně blízko od konkrétního bodu, se říká \uv{range query}. Datové struktury které tuto operaci akcelerují, jsou například fixní mřížka, dynamická mřížka nebo quad-tree.
@@ -754,21 +745,30 @@ Program klienta se skládá z třídy \inlcpp{World}, která reprezentuje stav a
\subsubsection{Klient Replikátoru} \subsubsection{Klient Replikátoru}
Abychom oddělili to, jak replikátor funguje, vytvořili jsme pro něj na straně klienta ovladač. To nám později umožnilo měnit protokol mezi klientem a server podle potřeby. Komponenta pouze přijme snapshot od serveru, provede autentizaci a pak podle něj změní stav na klientovi. Abychom oddělili to, jak replikátor funguje, vytvořili jsme pro něj na straně klienta ovladač. To nám později umožnilo měnit protokol mezi klientem a serverem podle potřeby. Komponenta pouze přijme snapshot od serveru, provede autentizaci a pak podle něj změní stav na klientovi.
\subsubsection{Interpolace} \subsubsection{Interpolace}
Když jsme začali systém měřit, zjistili jsme, že vysoká frekvence replikace až příliš zatěžuje síť. Graf s průměry pro počet hráčů vidíme na grafu. Snížili jsme proto frekvenci na 20Hz. To snížilo zátěž na třetinu. Hra potom nebyla plynulá. Klient vykresloval s frekvencí 60Hz, ale aktualizace pozice s frekvencí 20Hz způsobily neplynulý pohyb. Řešení je na klientovi interpolovat spojité proměnné, jako pozice nebo rotace. Když jsme začali systém měřit, zjistili jsme, že vysoká frekvence replikace až příliš zatěžuje síť. Snížili jsme proto frekvenci na 20Hz. To snížilo zátěž na třetinu. Hra potom nebyla plynulá. Klient vykresloval s frekvencí 60Hz, ale aktualizace pozice s frekvencí 20Hz způsobila neplynulý pohyb. Řešení zůstává na klientovi, který může interpolovat\cite{interpolation1} \cite{interpolation2} spojité proměnné, jako je pozice nebo rotace.
\begin{figure}
\begin{center}
\includegraphics[width=1.0\textwidth]{graphics/interpolation.png}
\end{center}
\caption{Graf interpolace}
\label{fig:interpolation}
\end{figure}
Vytvořili jsme novou komponentu \uv{interpolátor}. Ta umožňuje zapsat pozici entity v konkrétní čas. Komponenta si udržuje časovou osu stavu pozice. Zároveň umožňuje číst pozici entity pro konkrétní čas. Pokud je vybraný čas na ose mezi dvěma body, tak vrátí mezi nimi interpolovanou pozici. Pokud je vybraný čas až po posledním známém bodě na ose, tak vrací poslední známou hodnotu. Vytvořili jsme novou komponentu \uv{interpolátor}. Ta umožňuje zapsat pozici entity v konkrétní čas. Komponenta si udržuje časovou osu stavu pozice. Zároveň umožňuje číst pozici entity pro konkrétní čas. Pokud je vybraný čas na ose mezi dvěma body, tak vrátí mezi nimi interpolovanou pozici. Pokud je vybraný čas až po posledním známém bodě na ose, tak vrací poslední známou hodnotu.
Změnili jsme objekt, do kterého klient replikátoru zapisuje pozice entit na právě objekt interpolátoru. Do něj zapisuje původní sníženou frekvencí 20Hz. Řídící logika ale může z interpolátoru číst s vyšší frekvencí, například 60Hz. Aby čtecí funkce interpolátoru měla mezi čím interpolovat, není vhodné číst hned nejnovější hodnoty. Lepší je počkat, a interpolovat pozici určitý čas zpět. To má za následek zvýšení odezvy mezi vstupem od hráče a fyzickým posunem postavy hráče. Klient nejprve čeká na odpověď serveru a poté čeká ještě o jednu odpověď navíc. To není problém, pokud takto interpolujeme postavu, kterou neovládá přímo hráč. Rozdíl odezvy pár set milisekund bude zanedbatelný. Změnili jsme objekt, do kterého klient replikátoru zapisuje pozice entit na právě objekt interpolátoru. Do něj zapisuje původní sníženou frekvencí 20Hz. Řídící logika ale může z interpolátoru číst s vyšší frekvencí, například 60Hz. Aby čtecí funkce interpolátoru měla mezi čím interpolovat, není vhodné číst hned nejnovější hodnoty. Lepší je počkat, a interpolovat pozici určitý čas zpět. To má za následek zvýšení odezvy mezi vstupem od hráče a fyzickým posunem postavy hráče. Klient nejprve čeká na odpověď serveru a poté čeká ještě o jednu odpověď navíc. Na obrázku \ref{fig:interpolation} vidíme graf interpolace. Modré body jsou pozice, které klient dostal od serveru. Zelený graf je plynulá interpolovaná pozice.
\subsubsection{Rollback} \subsubsection{Rollback}
Interpolace zlepšila plynulost, ale nepříjemně zvýšila odezvu mezi vstupem od hráče a vyvolanou změnou stavu. Možným řešením je simulovat řídící logiku i na klientovi, ale pouze pro konkrétní entitu, kterou hráč ovládá. Odezva bude v podstatě nulová. Interpolace zlepšila plynulost, ale nepříjemně zvýšila odezvu mezi vstupem od hráče a vyvolanou změnou stavu. Možným řešením je simulovat řídící logiku i na klientovi, ale pouze pro konkrétní entitu, kterou hráč ovládá. Odezva bude v podstatě nulová.
Vytvořili jsme buffer, do kterého ukládáme konkrétní moment stavu, číslo iterace stavu a seznam akcí, která se v danou iteraci mají aplikovat. Pokud dostaneme snapshot pro snímek $x$ a z bufferu přečteme, jaký byl v iteraci stav. Pokud se neshodují, celý původní stav načteme a opravíme podle snapshotu. Následně znova aplikujeme všechny akce a přepíšeme tak náš buffer, až se dostaneme do aktuální iterace. Poté normálně pokračujeme s opraveným stavem. Vytvořili jsme buffer, do kterého ukládáme konkrétní moment stavu, číslo iterace stavu a seznam akcí, které se v danou iteraci mají aplikovat. Uvažujme situaci, kdy dostaneme snapshot pro snímek $x$ a zároveň z bufferu přečteme, jaký byl v iteraci stav. Pokud se neshodují, celý původní stav načteme a opravíme podle snapshotu. Následně opět aplikujeme všechny akce a přepíšeme náš buffer, až se dostaneme do aktuální iterace. Poté normálně pokračujeme s opraveným stavem.
@@ -781,13 +781,13 @@ Vytvořili jsme buffer, do kterého ukládáme konkrétní moment stavu, číslo
% Měl by poskytovat možnost, jak posílat zprávy nespolehlivě. % Měl by poskytovat možnost, jak posílat zprávy nespolehlivě.
% Zpráva přijde vždy buď celá, nebo vůbec. % Zpráva přijde vždy buď celá, nebo vůbec.
V aplikační vrstvě jsme definovali middleware protokol, který umožňuje obousměrné posílání typovaných zpráv. Typ zprávy je definován čtyř bytovým kladným číslem. Protokol jsme umístili do modulu \inlcpp{message_protocol}. Protokol využívá TCP, ale později implementaci změníme tak, aby používal náš protokol. Koncové body v protokolu se chovají jako fronta příchozích a fronta odchozích zpráv. Pro koncový bod můžeme definovat tzv. \uv{dispečer}, definovaný typem zprávy a anonymní funkci, která každou příchozí zprávu tohoto typu zpracuje. V aplikační vrstvě jsme definovali middleware protokol, který umožňuje obousměrné posílání typovaných zpráv. Typ zprávy je definován čtyř bytovým kladným číslem. Protokol jsme umístili do modulu \inlcpp{message_protocol}. Protokol využívá TCP, ale později implementaci změníme tak, aby používal náš protokol. Koncové body v protokolu se chovají jako fronta příchozích a fronta odchozích zpráv. Pro koncový bod můžeme definovat \uv{dispečer}, definovaný typem zprávy a anonymní funkci, která každou příchozí zprávu tohoto typu zpracuje.
% Popíšeme náš middleware pro posílání zpráv a jeho protokol založený na TCP. Poskytuje službu oboustranného peer-to-peer posílání zpráv na různé koncové body, které jsou identifikované čtyř bytovým číslem. Strana může pro libovolný identifikátor definovat handler, který se po získání takové zprávy spustí. Protokol zajišťuje spolehlivost na úrovni zpráv. To znamená, že zpráva dorazí buď celá, nebo vůbec. Později v kapitole \ref{sec:quicr} představíme náš protokol v transportní vrstvě, který umožňuje posílat zprávy spolehlivě i nespolehlivě. % Popíšeme náš middleware pro posílání zpráv a jeho protokol založený na TCP. Poskytuje službu oboustranného peer-to-peer posílání zpráv na různé koncové body, které jsou identifikované čtyř bytovým číslem. Strana může pro libovolný identifikátor definovat handler, který se po získání takové zprávy spustí. Protokol zajišťuje spolehlivost na úrovni zpráv. To znamená, že zpráva dorazí buď celá, nebo vůbec. Později v kapitole \ref{sec:quicr} představíme náš protokol v transportní vrstvě, který umožňuje posílat zprávy spolehlivě i nespolehlivě.
\subsubsection{Kódování zpráv} \subsubsection{Kódování zpráv}
Middleware využívá TCP, které na rozhraní při čtení a zápisu pracuje s proudem bytů, který není logicky rozdělený. Jediné pevné body jsou začátek a konec proudu. UDP na druhou stranu zaručuje, že celý buffer dat odeslaný přes \inlcpp{write} operaci bude přečtený vždy právě jedním voláním \inlcpp{read} operace. Náš protokol definuje oddělení zpráv tak, aby šli v proudu najít. Middleware využívá TCP, které na rozhraní při čtení a zápisu pracuje s proudem bytů, který není logicky rozdělený. Jediné pevné body jsou začátek a konec proudu. UDP na druhou stranu zaručuje, že celý buffer dat odeslaný přes \inlcpp{write} operaci bude přečtený vždy právě jedním voláním \inlcpp{read} operace. Náš protokol definuje oddělení zpráv tak, aby šly v proudu najít.
První čtyři byty každé zprávy jsou tzv. MAGIC číslo. Konstanta, která nemá jiný význam než záchytný bod při čtení. Dekodér v počátečním stavu hledá v proudu tuto hodnotu. Pokud ji do určitého počtu bytů nenajde, ukončí spojení z důvodu narušení protokolu. Když konstantu najde, přečte další čtyři byty, které reprezentují délku těla a další čtyři byty reprezentující ID koncového bodu. První čtyři byty každé zprávy jsou tzv. MAGIC číslo. Konstanta, která nemá jiný význam než záchytný bod při čtení. Dekodér v počátečním stavu hledá v proudu tuto hodnotu. Pokud ji do určitého počtu bytů nenajde, ukončí spojení z důvodu narušení protokolu. Když konstantu najde, přečte další čtyři byty, které reprezentují délku těla a další čtyři byty reprezentující ID koncového bodu.
@@ -806,13 +806,13 @@ Občas mohou nastat v proudu chyby, kdy zprávu nelze dekódovat, nebo nastane c
\subsection{Serializace} \subsection{Serializace}
Většinou nechceme používat middleware protokol, který na rozhraní používá n-tice bytů. Lepší je postavit obal, který umožní poslat zprávy reprezentované strukturou. Procesu, který ji převede na n-tici bytů se říká \uv{serializace}. Existují různé knihovny, které umí objekty serializovat. Některé umí serializovat přímo třídy definované v konkrétním programovacím jazyce. Jazyk C++ ale nemá runtime reflexi jako C\# nebo silná makra jako Rust, a tento způsob není možný. Druhá varianta je definovat tyto třídy ve speciálním jazyce pro definici schémat. Před sestavením programu z této definice vygenerujeme třídy v jazyce, který potřebujeme. Do tříd se vygenerují i metody pro serializaci. Tento přístup umožňuje například ProtoBuf, Cap'n'Proto a další. Velká motivace pro použití tohoto přístupu byla možnost reflexe, kterou tyto knihovny umožňují. Další výhoda je pro architekturu orientovanou na služby, kde každá služba je implementována v jiném jazyce, tak nemusíme definice lokalizovat. Většinou nechceme používat middleware protokol, který na rozhraní používá n-tice bytů. Lepší je postavit obal, který umožní poslat zprávy reprezentované strukturou. Procesu, který ji převede na n~-~tici bytů se říká \uv{serializace}. Existují různé knihovny, které umí objekty serializovat. Některé umí serializovat přímo třídy definované v konkrétním programovacím jazyce. Jazyk C++ ale nemá runtime reflexi jako C\# nebo silná makra jako Rust, a tento způsob není možný. Druhá varianta je definovat tyto třídy ve speciálním jazyce pro definici schémat. Před sestavením programu z této definice vygenerujeme třídy v jazyce, který potřebujeme. Do tříd se vygenerují i metody pro serializaci. Tento přístup umožňuje například ProtoBuf, Cap'n'Proto a další. Velká motivace pro použití tohoto přístupu byla možnost reflexe, kterou tyto knihovny umožňují. Další výhoda je pro architekturu orientovanou na služby, kde každá služba je implementována v jiném jazyce, takže nemusíme definice lokalizovat.
Hned na začátku jsme se rozhodli nepoužít JSON nebo XML, protože jsou to textové formáty a jejich forma je často větší než binárních formátů. Například číslo 1 000 000 se v JSON zakóduje do 7 bytů, i když binární reprezentace stejného čísla se vleze do 4 bytů. Rozdíl je téměř dvojnásobný. Každý atribut objektu se v JSONu reprezentuje řetězcem, namísto identifikačním číslem o 2 bytech, které by bylo menší. Výhody formátu jsou především liberalní zpracování, kdy se schémata dvou koncových bodů mohou i trochu lišit, ale pokud má zpráva všechny potřebné atributy, tak se strany domluví. Hned na začátku jsme se rozhodli nepoužít JSON nebo XML, protože jsou to textové formáty a jejich forma je často větší než binárních formátů. Například číslo 1 000 000 se v JSON zakóduje do 7 bytů, i když binární reprezentace stejného čísla se vleze do 4 bytů. Rozdíl je téměř dvojnásobný. Každý atribut objektu se v JSONu reprezentuje řetězcem, namísto identifikačním číslem o 2 bytech, které by bylo menší. Výhody formátu jsou především liberalní zpracování, kdy se schémata dvou koncových bodů mohou i mírně lišit, ale pokud má zpráva všechny potřebné atributy, tak se strany domluví.
Binární formáty tuto problematiku také řeší, například číslováním atributů, ale stále není řešení tak volné, jako u textových formátů. Obecně hrozí, že v binárním formátu je atribut navíc, nemusí se druhé straně podařit zprávu deserializovat. Proto se někdy JSON používá jako záložní formát, kdy dvě strany provedou handshake a domluví se na formátu. Pokud zjistí, že jedna strana používá starší definici schématu, mohou použít záložní JSON. Binární formáty tuto problematiku také řeší, například číslováním atributů, ale stále není řešení tak volné, jako u textových formátů. Obecně hrozí, že v binárním formátu je atribut navíc, nemusí se druhé straně podařit zprávu deserializovat. Proto se někdy JSON používá jako záložní formát, kdy dvě strany provedou handshake a domluví se na formátu. Pokud zjistí, že jedna strana používá starší definici schématu, mohou použít záložní JSON.
Rozhodli jsme se začít velmi rozšířeným ProtoBuf formátem. Začneme definicí zpráv mezi serverem a klientem. Vytvořili jsme WorldServerMessages.proto soubor, do kterého budeme zprávy definovat. Trochu formát \inlcpp{.proto} představíme. V kódu \ref{code:entity_spawn_message} vidíme definici zprávy, která říká, že si příjemce má do svého stavu přidat novou entitu. Obsahuje tři atributy: ID pro navázání budoucích zpráv o entitě, příznak, jestli se jedná o hráče a jméno. Rozhodli jsme se začít velmi rozšířeným ProtoBuf formátem. Začneme definicí zpráv mezi serverem a klientem. Vytvořili jsme WorldServerMessages.proto soubor, do kterého budeme zprávy definovat. Ve zkratce formát \inlcpp{.proto} představíme. V kódu \ref{code:entity_spawn_message} vidíme definici zprávy, která říká, že si příjemce má do svého stavu přidat novou entitu. Obsahuje tři atributy: ID pro navázání budoucích zpráv o entitě, dále příznak, zda se jedná o hráče a jméno.
\begin{kicode}{cpp}{}{cpp} \begin{kicode}{cpp}{}{cpp}
message EntitySpawnMessage { message EntitySpawnMessage {
@@ -825,7 +825,7 @@ Rozhodli jsme se začít velmi rozšířeným ProtoBuf formátem. Začneme defin
Jazyk vypadá podobně jako C. Nejprve použijeme klíčové slovo \inlcpp{message} a název typu. Do těla píšeme atributy oddělené středníkem. Všimněme si, že pro každý atribut musíme definovat jeho unikátní číslo. To slouží při identifikaci a pomáhá při úpravách definice, abychom měli kontrolu nad tím, pod jakým klíčem se hodnota serializuje. Jazyk vypadá podobně jako C. Nejprve použijeme klíčové slovo \inlcpp{message} a název typu. Do těla píšeme atributy oddělené středníkem. Všimněme si, že pro každý atribut musíme definovat jeho unikátní číslo. To slouží při identifikaci a pomáhá při úpravách definice, abychom měli kontrolu nad tím, pod jakým klíčem se hodnota serializuje.
FlatBuffers je opět protokol od Googlu, který se vyvýjel pro použití v herních enginech pro hry více hráčů. Jeho výhoda je, že není třeba zprávu "deserializovat". Instanci třídy čte atributy přímo z n-tice bytů. V případě 60 zpráv za vteřinu zprávy od stovek hráčů, je rozdíl mezi deserializací a FlatBuffers znát. FlatBuffers je opět protokol od Googlu, který se vyvíjel pro použití v herních enginech pro hry více hráčů. Jeho výhoda je, že není třeba zprávu \uv{deserializovat}. Instanci třídy čte atributy přímo z n-tice bytů. V případě 60 zpráv za vteřinu zprávy od stovek hráčů, je rozdíl mezi deserializací a FlatBuffers znát.
Posledním příkladem je Cap'n'Proto, čteno Captain Proto. Je to volně dostupný protokol, který nemá deserializaci, a je tak velmi rychlý. Jeho tvůrce navíc pracoval právě na ProtoBuf. Posledním příkladem je Cap'n'Proto, čteno Captain Proto. Je to volně dostupný protokol, který nemá deserializaci, a je tak velmi rychlý. Jeho tvůrce navíc pracoval právě na ProtoBuf.
@@ -844,16 +844,16 @@ Naše hra používala ke komunikaci mezi vrcholy protokol TCP. Zmínili jsme ale
Upustili jsme od QUIC paketů a definovali jsme právě jeden typ, který má v hlavičce ID příjemce a ID odesílatele. Každý paket obsahuje rámce. Rámce jsme také rozdělili na dva typy: datové a ovládací. Ovládací slouží pro handshake, ukončení spojení nebo nastavení jiných parametrů spojení a budou vždy doručené spolehlivě. Datové rámce obsahují aplikační data a mohou definovat svou spolehlivost. Ty, které budou obsahovat pozice hráčů, tak budeme moct odesílat nespolehlivě, zatímco změny stavu, jako změna barvy postavy, posíláme spolehlivě. Implementace se skládá ze dvou tříd: \uv{koncový bod} a \uv{spojení}. Upustili jsme od QUIC paketů a definovali jsme právě jeden typ, který má v hlavičce ID příjemce a ID odesílatele. Každý paket obsahuje rámce. Rámce jsme také rozdělili na dva typy: datové a ovládací. Ovládací slouží pro handshake, ukončení spojení nebo nastavení jiných parametrů spojení a budou vždy doručené spolehlivě. Datové rámce obsahují aplikační data a mohou definovat svou spolehlivost. Ty, které budou obsahovat pozice hráčů, tak budeme moct odesílat nespolehlivě, zatímco změny stavu, jako změna barvy postavy, posíláme spolehlivě. Implementace se skládá ze dvou tříd: \uv{koncový bod} a \uv{spojení}.
Objekt navázaného spojení je stavový stroj a fronta příchozích a fronta odchozích zpráv, podobně jako TCP spojení. Stavy se mění v reakci na příchozí ovládací rámce. Každý objekt spojení má přiřazeno alespoň jedno ID reprezentované osmi bytovým číslem. Tento objekt přímo nepracuje se socketem, ale poskytuje rozhraní, kterým dostává získané zprávy, které odeslala druhá strana. Právě tento objekt překládá n-tici bytů na rámce a postupně je zpracovává. Stavový stroj je důležitý hlavně v procesu handshake, který definujeme níže. Objekt navázaného spojení je stavový stroj a fronty příchozích a odchozích zpráv, podobně jako TCP spojení. Stavy se mění v reakci na příchozí ovládací rámce. Každý objekt spojení má přiřazeno alespoň jedno ID reprezentované osmi bytovým číslem. Tento objekt přímo nepracuje se socketem, ale poskytuje rozhraní, kterým dostává získané zprávy, které odeslala druhá strana. Právě tento objekt překládá n-tici bytů na rámce a postupně je zpracovává. Stavový stroj je důležitý hlavně v procesu handshake, který definujeme níže.
Objekt pro koncový bod se stará o soket pro UDP: čtení a zápis na něj, a udržuje si registr objektů spojení. Při získání datagramu ze socketu ověří, že má správný formát. Podle protokolu by každý datagram měl obsahovat hlavičku s magickým číslem a ID spojení. Koncový bod přečte ID spojení a podle svého registru vyhledá objekt spojení, kterému tělo zprávy předá. Pokud v registru klíč pro získané ID není, koncový bod si objekt spojení vytvoří v počátečním stavu a začíná proces zvaný handshake. Tento proces popíšeme v podkapitole \ref{sec:quicr_handshake}. Objekt pro koncový bod se stará o soket pro UDP: čtení a zápis na něj, a udržuje si registr objektů spojení. Při získání datagramu ze socketu ověří, že má správný formát. Podle protokolu by každý datagram měl obsahovat hlavičku s magickým číslem a ID spojení. Koncový bod přečte ID spojení a podle svého registru vyhledá objekt spojení, kterému předá tělo zprávy. Pokud v registru není klíč získaného ID, koncový bod si objekt spojení vytvoří v počátečním stavu a začíná proces zvaný handshake. Tento proces popíšeme v podkapitole \ref{sec:quicr_handshake}.
Nechtěli jsme, aby si implementace QUICr spravovala vlastní asynchronní kontext. Namísto toho jsme definovali metodu pro aktualizaci, která posbírá zprávy od jednotlivých navázaných spojení a pošle je. Následně přečte všechna data ze soketu a roztřídí je do navázaných spojení. Nechtěli jsme, aby si implementace QUICr spravovala vlastní asynchronní kontext. Namísto toho jsme definovali metodu pro aktualizaci, která posbírá zprávy od jednotlivých navázaných spojení a pošle je. Následně přečte všechna data ze soketu a roztřídí je do navázaných spojení.
\subsubsection{Rámce} \subsubsection{Rámce}
Hlavním prvkem datového přenosu v protokolu jsou rámce. Jak už bylo nastíněno, dělíme je na kontrolní a datové. Pro využití nespolehlivosti jsme u každého datového rámce umožňili definovat, jestli je spolehlivý nebo nespolehlivý. O spolehlivost obecně se stará komponenta \inlcpp{ReliabilityUnit}, kterou podpobněji představíme v kapitole \ref{sec:quicr_reliability}. Hlavním prvkem datového přenosu v protokolu jsou rámce. Jak už bylo nastíněno, dělíme je na kontrolní a datové. Pro využití nespolehlivosti jsme u každého datového rámce umožňili definovat, jestli je spolehlivý nebo nespolehlivý. O spolehlivost se obecně stará komponenta \inlcpp{ReliabilityUnit}, kterou podpobněji představíme v kapitole \ref{sec:quicr_reliability}.
Rámec je n-tice bytů, která se skládá z hlavičky a těla. V hlavičce máme ID cílového spojení a ID počátečního spojení. Rámec je n-tice bytů, která se skládá z hlavičky a těla. V hlavičce máme ID cílového spojení a ID počátečního spojení.
@@ -866,7 +866,7 @@ Rámec je n-tice bytů, která se skládá z hlavičky a těla. V hlavičce mám
\subsubsection{Handshake} \label{sec:quicr_handshake} \subsubsection{Handshake} \label{sec:quicr_handshake}
Objekt navázaného spojení obsahuje stavový stroj a postupně mezi stavy přechází. Počáteční stav je \inlcpp{Closed}. Jedna strana musí začít a odeslat paket s \inlcpp{Hello} rámcem. Po obdržení se stavový stroj druhé strany přesune do \inlcpp{ReceivedHello} a spolehlivě odešle \inlcpp{Hello}. Když strana dostane rámec \inlcpp{Hello} tak ví, že v hlavičce paketu je cílové i lokální ID. Proto už touto výměnou se strany shodli na ID navázaného spojení, které budou používat. Poté už si vymění rámec \inlcpp{HandshakeDone} a spojení je navázané a připravené k posílání.C elý stavový diagram vidíme na obrázku \ref{fig:quicr_handshake}. Objekt navázaného spojení obsahuje stavový stroj a postupně mezi stavy přechází. Počáteční stav je \inlcpp{Closed}. Jedna strana musí začít a odeslat paket s \inlcpp{Hello} rámcem. Po obdržení se stavový stroj druhé strany přesune do \inlcpp{ReceivedHello} a spolehlivě odešle \inlcpp{Hello}. Jakmile strana dostane rámec \inlcpp{Hello} tak ví, že v hlavičce paketu je cílové i lokální ID. Proto set už touto výměnou strany shodly na ID navázaného spojení, které budou používat. Poté už si vymění rámec \inlcpp{HandshakeDone} a spojení je navázané a připravené k posílání. Celý stavový diagram vidíme na obrázku \ref{fig:quicr_handshake}.
% Nové připojení projde všechny rámce v paketu. Měl by narazit na rámec Hello, který když najde, a je ve stavu `Initial`, tak z hlavičky zjistí unikátní ID druhé strany a uloží si ho. Reaguje na rámec tak, že druhé straně odešle přes koncový bod paket, který obsahuje: rámec ACK o tom, že paket s číslem přijal, a rámec Hello. ACK si pro začátek představme zakódovaný jako: první 4 byty reprezentují kladné celé číslo pro počet rámců, řekněme $n$, které chceme označit jako přijaté. Následně přečteme $4n$ bytů. Každé 4 byty představují číslo paketu, který označíme jako ACKed. Jednotce, která udržuje stav o tom, jaké pakety jsou potřeba oznámit jako ACK a které je třeba poslat znovu, budu říkat `RealiabilityUnit` a podrobněji ji rozeberu později. % Nové připojení projde všechny rámce v paketu. Měl by narazit na rámec Hello, který když najde, a je ve stavu `Initial`, tak z hlavičky zjistí unikátní ID druhé strany a uloží si ho. Reaguje na rámec tak, že druhé straně odešle přes koncový bod paket, který obsahuje: rámec ACK o tom, že paket s číslem přijal, a rámec Hello. ACK si pro začátek představme zakódovaný jako: první 4 byty reprezentují kladné celé číslo pro počet rámců, řekněme $n$, které chceme označit jako přijaté. Následně přečteme $4n$ bytů. Každé 4 byty představují číslo paketu, který označíme jako ACKed. Jednotce, která udržuje stav o tom, jaké pakety jsou potřeba oznámit jako ACK a které je třeba poslat znovu, budu říkat `RealiabilityUnit` a podrobněji ji rozeberu později.
@@ -875,16 +875,16 @@ Objekt navázaného spojení obsahuje stavový stroj a postupně mezi stavy pře
\begin{description} \begin{description}
\item[{Closed}] \hfill \\ \item[{Closed}] \hfill \\
Počátečním stavem je `Closed`. Zároveň se jedná o stav, do kterého se spojení dostane, pokud dlouho s druhou stranou nekomunikuje. Počátečním stavem je \inlcpp{Closed}. Zároveň se jedná o stav, do kterého se spojení dostane, pokud dlouho s druhou stranou nekomunikuje.
\item[{SentHello}] \hfill \\ \item[{SentHello}] \hfill \\
Po odeslání \texttt{Hello} rámce se spojení dostane do stavu \texttt{SentHello}. V tomto stavu čeká na \texttt{Hello} rámec od druhé strany. Po odeslání \inlcpp{Hello} rámce se spojení dostane do stavu \inlcpp{SentHello}. V tomto stavu čeká na \inlcpp{Hello} rámec od druhé strany.
\item[{ReceivedHello}] \hfill \\ \item[{ReceivedHello}] \hfill \\
Jakmile strana dostane rámec \texttt{Hello}, přejde do stavu \texttt{ReceivedHello}. V ten moment čeká na potvrzení, že spojení bylo navázáno, tedy rámec \texttt{HandshakeDone}. Jakmile strana dostane rámec \inlcpp{Hello}, přejde do stavu \inlcpp{ReceivedHello}. V ten moment čeká na potvrzení, že spojení bylo navázáno, tedy rámec \inlcpp{HandshakeDone}.
\item[{Established}] \hfill \\ \item[{Established}] \hfill \\
Po odeslání HandshakeDone zprávy se klient dostane do stavy Established. Jakmile server přijme zprávu HandshakeDone, taky se dostává do stavu Established. Po odeslání \inlcpp{HandshakeDone} zprávy se klient dostane do stavu \inlcpp{Established}. Jakmile server přijme zprávu \inlcpp{HandshakeDone}, taky se dostává do stavu \inlcpp{Established}.
\end{description} \end{description}
@@ -906,16 +906,16 @@ Spolehlivost řeší komponenta \inlcpp{ReliabilityUnit}, která si udržuje fro
\begin{description} \begin{description}
\item[\texttt{push\_reliable\_frame\_to\_send(deadline, frame)}] \hfill \\ \item[\inlcpp{push\_reliable\_frame\_to\_send(deadline, frame)}] \hfill \\
Uloží si zakódovaný rámec a nastaví si u něj čas odeslání. Jakmile bude po deadline, jednotka se bude snažit dostat rámec do dalšího datagramu. Rámec se ukládá v zakódované podobě tak, aby byla předpovídatelná jeho velikost a snadno se odhadovalo, jestli se do dalšího datagramu vleze. Uloží si zakódovaný rámec a nastaví si u něj čas odeslání. Jakmile bude po deadline, jednotka se bude snažit dostat rámec do dalšího datagramu. Rámec se ukládá v zakódované podobě tak, aby byla předpovídatelná jeho velikost a snadno se odhadovalo, jestli se do dalšího datagramu vleze.
\item[\texttt{peek/pop\_reliable\_frames\_to\_send(packet\_number)}] \hfill \\ \item[\inlcpp{peek/pop\_reliable\_frames\_to\_send(packet\_number)}] \hfill \\
Vrátí rámce, které je potřeba v tomto okamžiku odeslat. Číslo paketu \texttt{packet\_number} si jednotka přiřadí jako verifikátor doručení rámce, který metoda vrátí. To znamená, že když toto číslo přijde v \texttt{Ack} rámci, bude jednotka vědět, který rámec může odebrat. Zároveň může mít vícero vazeb čísla paketu na jeden rámec. Libovolné číslo paketu smaže provázaný rámec. Důvod je, aby mohlo být v oběhu více paketů se stejným rámcem. Vrátí rámce, které je potřeba v tomto okamžiku odeslat. Číslo paketu \inlcpp{packet\_number} si jednotka přiřadí jako verifikátor doručení rámce, který metoda vrátí. To znamená, že když toto číslo přijde v \inlcpp{Ack} rámci, bude jednotka vědět, který rámec může odebrat. Zároveň může mít vícero vazeb čísla paketu na jeden rámec. Libovolné číslo paketu smaže provázaný rámec. Důvod je, aby mohlo být v oběhu více paketů se stejným rámcem.
\item[\texttt{push\_ack(packet\_number)}] \hfill \\ \item[\inlcpp{push\_ack(packet\_number)}] \hfill \\
Vloží do seznamu čísel paketů. Celý tento seznam se odešle v \texttt{Ack} rámci v dalším datagramu. Vloží do seznamu čísel paketů. Celý tento seznam se odešle v \inlcpp{Ack} rámci v dalším datagramu.
\item[\texttt{peek/pop\_acks\_to\_send()}] \hfill \\ \item[\inlcpp{peek/pop\_acks\_to\_send()}] \hfill \\
Vrátí seznam čísel paketů, které musí druhé straně oznámit jako doručené. Vrátí seznam čísel paketů, které musí druhé straně oznámit jako doručené.
\end{description} \end{description}
@@ -971,7 +971,7 @@ Při implementaci jsme zjistili, že je dobré začít testy, které definují j
\subsection{Horizontální škálování} \subsection{Horizontální škálování}
Při nárustu počtu hráčů už nemusí stačit jeden výpočetní server. Poté je nutné využít výkon více počítačů technikou zvanou \uv{horizontální škálování}. To znamená, že do systému přidáváme servery, které si tak rovnoměrně rozdělí práci. V případě naší hry jsme rozdělili herní svět na zóny a o každou se stará jiný server. Takový server je \uv{zone server} a dohromady tvoří \uv{zone cluster}. Do systému jsme dále přidali \uv{cluster koordinátora}, který říká, který zone server má jakou zónu. Model mezi koordinátorem a zone serverem je klient-server. Na druhou stranu zone servery mezi sebou komunikují přímo a využívají model peer-to-peer. Při nárustu počtu hráčů už nemusí stačit jeden výpočetní server. Poté je nutné využít výkon více počítačů zároveň technikou zvanou \uv{horizontální škálování}. To znamená, že do systému přidáváme servery, které si tak rovnoměrně rozdělí práci. V případě naší hry jsme rozdělili herní svět na zóny a o každou se stará jiný server. Takový server je \uv{zone server} a dohromady tvoří \uv{zone cluster}. Do systému jsme dále přidali \uv{cluster koordinátora}, který říká, který zone server má jakou zónu. Model mezi koordinátorem a zone serverem je klient-server. Na druhou stranu zone servery mezi sebou komunikují přímo a využívají model peer-to-peer.
Představíme, jak spolu zone servery komunikují. Využijeme k tomu už existující komponenty: replikátor a manažera zájmu. Nejprve jsme stav hry, manažera zájmu a fyzický svět do třídy \inlcpp{ZoneManager}. Tuto třídu obalíme \inlcpp{ZoneServer} třídou. Ta bude obsahovat replikátor a \inlcpp{ZoneCoordinatorClient}. Manažer zón si bude udržovat registr sousedních zón a bude se k ním chovat jako klasickým klientům. Rozdíl bude ten, že klient má jako zájem definovaný pouze bod a manažer zájmu klientovi přiřadí do zájmu entity, které jsou od bodu v dostatečné vzdálenosti. Sousedi budou mít jako zájem definovanou celou jejich plochu. Manažer zájmu má nyní na rozhraní dvě metody: \inlcpp{register\_client\_interest(interest\_id, entity)} a \inlcpp{register\_zone\_interest(interest\_id, area)}. Každý zájem je definovaný unikátním ID. O to, jaké entity pak konkrétní zájem zajímají získáme voláním \inlcpp{get_interest(interest_id)}. Představíme, jak spolu zone servery komunikují. Využijeme k tomu už existující komponenty: replikátor a manažera zájmu. Nejprve jsme stav hry, manažera zájmu a fyzický svět do třídy \inlcpp{ZoneManager}. Tuto třídu obalíme \inlcpp{ZoneServer} třídou. Ta bude obsahovat replikátor a \inlcpp{ZoneCoordinatorClient}. Manažer zón si bude udržovat registr sousedních zón a bude se k ním chovat jako klasickým klientům. Rozdíl bude ten, že klient má jako zájem definovaný pouze bod a manažer zájmu klientovi přiřadí do zájmu entity, které jsou od bodu v dostatečné vzdálenosti. Sousedi budou mít jako zájem definovanou celou jejich plochu. Manažer zájmu má nyní na rozhraní dvě metody: \inlcpp{register\_client\_interest(interest\_id, entity)} a \inlcpp{register\_zone\_interest(interest\_id, area)}. Každý zájem je definovaný unikátním ID. O to, jaké entity pak konkrétní zájem zajímají získáme voláním \inlcpp{get_interest(interest_id)}.
+30 -30
View File
@@ -18,43 +18,43 @@
\contentsline {subsubsection}{\numberline {3.3.3}QUIC}{18}{subsubsection.3.3.3}% \contentsline {subsubsection}{\numberline {3.3.3}QUIC}{18}{subsubsection.3.3.3}%
\contentsline {section}{\numberline {4}Hra}{21}{section.4}% \contentsline {section}{\numberline {4}Hra}{21}{section.4}%
\contentsline {subsection}{\numberline {4.1}Engine}{21}{subsection.4.1}% \contentsline {subsection}{\numberline {4.1}Engine}{21}{subsection.4.1}%
\contentsline {subsubsection}{\numberline {4.1.1}Fyzický engine}{22}{subsubsection.4.1.1}% \contentsline {subsubsection}{\numberline {4.1.1}Fyzický engine}{21}{subsubsection.4.1.1}%
\contentsline {subsubsection}{\numberline {4.1.2}Vykreslování}{23}{subsubsection.4.1.2}% \contentsline {subsubsection}{\numberline {4.1.2}Vykreslování}{22}{subsubsection.4.1.2}%
\contentsline {subsubsection}{\numberline {4.1.3}Entity-Component-System}{23}{subsubsection.4.1.3}% \contentsline {subsubsection}{\numberline {4.1.3}Entity-Component-System}{22}{subsubsection.4.1.3}%
\contentsline {subsubsection}{\numberline {4.1.4}ImGui}{24}{subsubsection.4.1.4}% \contentsline {subsubsection}{\numberline {4.1.4}ImGui}{24}{subsubsection.4.1.4}%
\contentsline {section}{\numberline {5}Hra více hráčů}{26}{section.5}% \contentsline {section}{\numberline {5}Hra více hráčů}{25}{section.5}%
\contentsline {subsection}{\numberline {5.1}Server}{27}{subsection.5.1}% \contentsline {subsection}{\numberline {5.1}Server}{25}{subsection.5.1}%
\contentsline {subsubsection}{\numberline {5.1.1}Registr klientů}{27}{subsubsection.5.1.1}% \contentsline {subsubsection}{\numberline {5.1.1}Registr klientů}{26}{subsubsection.5.1.1}%
\contentsline {subsubsection}{\numberline {5.1.2}Server Replikátoru}{28}{subsubsection.5.1.2}% \contentsline {subsubsection}{\numberline {5.1.2}Server Replikátoru}{27}{subsubsection.5.1.2}%
\contentsline {subsubsection}{\numberline {5.1.3}Správa zájmů}{28}{subsubsection.5.1.3}% \contentsline {subsubsection}{\numberline {5.1.3}Správa zájmů}{27}{subsubsection.5.1.3}%
\contentsline {subsection}{\numberline {5.2}Klient}{28}{subsection.5.2}% \contentsline {subsection}{\numberline {5.2}Klient}{27}{subsection.5.2}%
\contentsline {subsubsection}{\numberline {5.2.1}Klient Replikátoru}{28}{subsubsection.5.2.1}% \contentsline {subsubsection}{\numberline {5.2.1}Klient Replikátoru}{27}{subsubsection.5.2.1}%
\contentsline {subsubsection}{\numberline {5.2.2}Interpolace}{28}{subsubsection.5.2.2}% \contentsline {subsubsection}{\numberline {5.2.2}Interpolace}{27}{subsubsection.5.2.2}%
\contentsline {subsubsection}{\numberline {5.2.3}Rollback}{29}{subsubsection.5.2.3}% \contentsline {subsubsection}{\numberline {5.2.3}Rollback}{28}{subsubsection.5.2.3}%
\contentsline {subsection}{\numberline {5.3}Posílání zpráv}{29}{subsection.5.3}% \contentsline {subsection}{\numberline {5.3}Posílání zpráv}{28}{subsection.5.3}%
\contentsline {subsubsection}{\numberline {5.3.1}Kódování zpráv}{30}{subsubsection.5.3.1}% \contentsline {subsubsection}{\numberline {5.3.1}Kódování zpráv}{29}{subsubsection.5.3.1}%
\contentsline {subsubsection}{\numberline {5.3.2}Implementace}{30}{subsubsection.5.3.2}% \contentsline {subsubsection}{\numberline {5.3.2}Implementace}{29}{subsubsection.5.3.2}%
\contentsline {subsubsection}{\numberline {5.3.3}Detekce a náprava chyb}{30}{subsubsection.5.3.3}% \contentsline {subsubsection}{\numberline {5.3.3}Detekce a náprava chyb}{29}{subsubsection.5.3.3}%
\contentsline {subsection}{\numberline {5.4}Serializace}{30}{subsection.5.4}% \contentsline {subsection}{\numberline {5.4}Serializace}{30}{subsection.5.4}%
\contentsline {subsection}{\numberline {5.5}Protokol QUICr}{32}{subsection.5.5}% \contentsline {subsection}{\numberline {5.5}Protokol QUICr}{31}{subsection.5.5}%
\contentsline {subsubsection}{\numberline {5.5.1}Rámce}{33}{subsubsection.5.5.1}% \contentsline {subsubsection}{\numberline {5.5.1}Rámce}{32}{subsubsection.5.5.1}%
\contentsline {subsubsection}{\numberline {5.5.2}Handshake}{33}{subsubsection.5.5.2}% \contentsline {subsubsection}{\numberline {5.5.2}Handshake}{32}{subsubsection.5.5.2}%
\contentsline {subsubsection}{\numberline {5.5.3}Spolehlivost}{33}{subsubsection.5.5.3}% \contentsline {subsubsection}{\numberline {5.5.3}Spolehlivost}{34}{subsubsection.5.5.3}%
\contentsline {subsubsection}{\numberline {5.5.4}Enkodér}{35}{subsubsection.5.5.4}% \contentsline {subsubsection}{\numberline {5.5.4}Enkodér}{34}{subsubsection.5.5.4}%
\contentsline {subsubsection}{\numberline {5.5.5}Testování}{36}{subsubsection.5.5.5}% \contentsline {subsubsection}{\numberline {5.5.5}Testování}{35}{subsubsection.5.5.5}%
\contentsline {subsection}{\numberline {5.6}Horizontální škálování}{36}{subsection.5.6}% \contentsline {subsection}{\numberline {5.6}Horizontální škálování}{35}{subsection.5.6}%
\contentsline {subsection}{\numberline {5.7}Výsledná hra}{37}{subsection.5.7}% \contentsline {subsection}{\numberline {5.7}Výsledná hra}{36}{subsection.5.7}%
\contentsline {section}{\numberline {6}Měřění}{39}{section.6}% \contentsline {section}{\numberline {6}Měřění}{38}{section.6}%
\contentsline {subsection}{\numberline {6.1}Metriky}{39}{subsection.6.1}% \contentsline {subsection}{\numberline {6.1}Metriky}{38}{subsection.6.1}%
\contentsline {subsubsection}{\numberline {6.1.1}PostgreSQL}{39}{subsubsection.6.1.1}% \contentsline {subsubsection}{\numberline {6.1.1}PostgreSQL}{39}{subsubsection.6.1.1}%
\contentsline {subsubsection}{\numberline {6.1.2}TimescaleDB}{39}{subsubsection.6.1.2}% \contentsline {subsubsection}{\numberline {6.1.2}TimescaleDB}{39}{subsubsection.6.1.2}%
\contentsline {subsubsection}{\numberline {6.1.3}Grafana}{40}{subsubsection.6.1.3}% \contentsline {subsubsection}{\numberline {6.1.3}Grafana}{39}{subsubsection.6.1.3}%
\contentsline {subsubsection}{\numberline {6.1.4}Tracy}{40}{subsubsection.6.1.4}% \contentsline {subsubsection}{\numberline {6.1.4}Tracy}{40}{subsubsection.6.1.4}%
\contentsline {subsubsection}{\numberline {6.1.5}Klientská aplikace}{40}{subsubsection.6.1.5}% \contentsline {subsubsection}{\numberline {6.1.5}Klientská aplikace}{40}{subsubsection.6.1.5}%
\contentsline {subsection}{\numberline {6.2}QUICr}{41}{subsection.6.2}% \contentsline {subsection}{\numberline {6.2}QUICr}{40}{subsection.6.2}%
\contentsline {subsection}{\numberline {6.3}Optimalizace replikátoru}{43}{subsection.6.3}% \contentsline {subsection}{\numberline {6.3}Optimalizace replikátoru}{42}{subsection.6.3}%
\contentsline {subsection}{\numberline {6.4}Optimalizace manažera zájmů}{45}{subsection.6.4}% \contentsline {subsection}{\numberline {6.4}Optimalizace manažera zájmů}{45}{subsection.6.4}%
\contentsline {subsection}{\numberline {6.5}Peer-to-peer}{46}{subsection.6.5}% \contentsline {subsection}{\numberline {6.5}Peer-to-peer}{45}{subsection.6.5}%
\contentsline {section}{Z\'av\v er}{48}{section*.3}% \contentsline {section}{Z\'av\v er}{48}{section*.3}%
\babel@toc {czech}{}\relax \babel@toc {czech}{}\relax
\babel@toc {czech}{}\relax \babel@toc {czech}{}\relax