Compare commits

...

13 Commits
main ... main

39 changed files with 236 additions and 110 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
.sass-cache/ .sass-cache/
website/_sass/bootstrap/ website/_sass/bootstrap/
website/_site/ website/_site/
website/config.yml website/_config.yml
web.tar.bz2 web.tar.bz2

View File

@ -1,3 +1,7 @@
## This repository is no longer being updated
This code is now part of the onFOSS organization. Refer to https://git.libregaming.org/onFOSS/Gameserver for the up-to-date version of the game server.
# Game server # Game server
This is a collection of scripts to deploy game servers on Debian 11. All game This is a collection of scripts to deploy game servers on Debian 11. All game
@ -37,7 +41,9 @@ DOMAINNAME=play.jarno.ca HOSTEDBYNAME=DeathByDenim ./deploy.sh
``` ```
This will download all the game servers, install them, configure them, and start them up. It should take less than an hour for all game servers to be up and running. This will download all the game servers, install them, configure them, and start them up. It should take less than an hour for all game servers to be up and running.
It also retrieves a certificate for Let's Encrypt for the web interface. If you don't want the certificate, you can also specify `NOSSL=1`. If you don't have a domainname, just use the IP address.
It also retrieves a certificate for Let's Encrypt for the web interface. If you don't want the certificate, you can also specify `NOSSL=1`. This will also convert all internal links to http, meaning that if you add a certificate later things will break due to modern browser not allowing mixed http/https content.
There is also support for generating just the website without the game server which is useful if you want to host the website somewhere else while your main server is down. There is also support for generating just the website without the game server which is useful if you want to host the website somewhere else while your main server is down.
``` ```

View File

@ -67,7 +67,7 @@ apt install --assume-yes \
fuse g++ gcc curl firewalld automake autoconf libtool \ fuse g++ gcc curl firewalld automake autoconf libtool \
libcurl3-dev libc-ares-dev zlib1g-dev libncurses-dev make python3-aiohttp \ libcurl3-dev libc-ares-dev zlib1g-dev libncurses-dev make python3-aiohttp \
nginx-core certbot python3-certbot-nginx sudo python3-psutil \ nginx-core certbot python3-certbot-nginx sudo python3-psutil \
ldc dub libenet-dev python3-bcrypt jq telnet jekyll ldc dub libenet-dev python3-bcrypt jq telnet jekyll ruby-jekyll-feed
# Create the user for running the game servers # Create the user for running the game servers
if ! getent passwd ${systemuser}; then if ! getent passwd ${systemuser}; then

View File

@ -39,13 +39,38 @@ if [ -d "$(dirname "$0")"/../website/_sass/bootstrap ]; then
fi fi
mv ${TMPDIR:-/tmp}/bootstrap/bootstrap-5.2.3/scss ${webroot}/_sass/bootstrap mv ${TMPDIR:-/tmp}/bootstrap/bootstrap-5.2.3/scss ${webroot}/_sass/bootstrap
rm -r ${TMPDIR:-/tmp}/bootstrap.zip ${TMPDIR:-/tmp}/bootstrap rm -r ${TMPDIR:-/tmp}/bootstrap.zip ${TMPDIR:-/tmp}/bootstrap
if [ x"$NOSSL" = "x" ] || [ $NOSSL -ne 1 ]; then
ssl="true"
s_for_https="s"
else
ssl="false"
s_for_https=""
fi
cat > ${webroot}/_config.yml <<EOF cat > ${webroot}/_config.yml <<EOF
title: "onFOSS"
description: >
onFOSS-LAN is a online, "Free (as Freedom) and Open Source" LAN-Party hosted by ${HOSTEDBYNAME} The goal is to get people together, enjoying the art of computer games and having a great time in these days. The FOSS community is a place of being open minded and acceptance to all different kinds of people with the focus of fully transparent systems and protecting individuals. So it does not matter if you are on Windows, Mac or Linux and it is also NOT necessary to have a PC MASTERRACE setup to run those games.
url: http${s_for_https}://${DOMAINNAME}
content: content:
hosted_by_name: "${HOSTEDBYNAME}" hosted_by_name: "${HOSTEDBYNAME}"
domain_name: "${DOMAINNAME}" domain_name: "${DOMAINNAME}"
offline: true offline: true
ssl: true ssl: ${ssl}
md5password: "$(echo -n "${systempassword}" | md5sum | cut -d' ' -f1)" md5password: "$(echo -n "${systempassword}" | md5sum | cut -d' ' -f1)"
defaults:
-
scope:
path: ""
type: "posts"
values:
layout: "post"
plugins:
- jekyll-feed
EOF EOF
jekyll build --source ${webroot} --destination ${webroot}/_site jekyll build --source ${webroot} --destination ${webroot}/_site
tar -cjf web.tar.bz2 --directory="${webroot}/_site" . tar -cjf web.tar.bz2 --directory="${webroot}/_site" .

View File

@ -27,8 +27,10 @@ firewall-cmd --reload
# Request SSL certificate. This assumes DNS has been set up already # Request SSL certificate. This assumes DNS has been set up already
if [ x"$NOSSL" = "x" ] || [ $NOSSL -ne 1 ]; then if [ x"$NOSSL" = "x" ] || [ $NOSSL -ne 1 ]; then
ssl="true" ssl="true"
s_for_https="s"
certbot -n --nginx -d ${DOMAINNAME} -d www.${DOMAINNAME} --agree-tos -m "${letsencryptemail}" certbot -n --nginx -d ${DOMAINNAME} -d www.${DOMAINNAME} --agree-tos -m "${letsencryptemail}"
else else
s_for_https=""
ssl="false" ssl="false"
fi fi
@ -41,12 +43,28 @@ fi
mv ${TMPDIR:-/tmp}/bootstrap/bootstrap-5.2.3/scss "$(dirname "$0")"/../website/_sass/bootstrap mv ${TMPDIR:-/tmp}/bootstrap/bootstrap-5.2.3/scss "$(dirname "$0")"/../website/_sass/bootstrap
rm -r ${TMPDIR:-/tmp}/bootstrap.zip ${TMPDIR:-/tmp}/bootstrap rm -r ${TMPDIR:-/tmp}/bootstrap.zip ${TMPDIR:-/tmp}/bootstrap
cat > "$(dirname "$0")"/../website/_config.yml <<EOF cat > "$(dirname "$0")"/../website/_config.yml <<EOF
title: "onFOSS"
description: >
onFOSS-LAN is a online, "Free (as Freedom) and Open Source" LAN-Party hosted by ${HOSTEDBYNAME}. The goal is to get people together, enjoying the art of computer games and having a great time in these days. The FOSS community is a place of being open minded and acceptance to all different kinds of people with the focus of fully transparent systems and protecting individuals. So it does not matter if you are on Windows, Mac or Linux and it is also NOT necessary to have a PC MASTERRACE setup to run those games.
url: http${s_for_https}://${DOMAINNAME}
content: content:
hosted_by_name: "${HOSTEDBYNAME}" hosted_by_name: "${HOSTEDBYNAME}"
domain_name: "${DOMAINNAME}" domain_name: "${DOMAINNAME}"
offline: false offline: false
ssl: ${ssl} ssl: ${ssl}
md5password: "$(echo -n "${systempassword}" | md5sum | cut -d' ' -f1)" md5password: "$(echo -n "${systempassword}" | md5sum | cut -d' ' -f1)"
defaults:
-
scope:
path: ""
type: "posts"
values:
layout: "post"
plugins:
- jekyll-feed
EOF EOF
jekyll build --source "$(dirname "$0")"/../website --destination /var/www/html jekyll build --source "$(dirname "$0")"/../website --destination /var/www/html

View File

@ -1,8 +1,8 @@
<h4>{{ event.date | date: "%A %d %B %Y, %H:%M %Z" }}</h4> <h4>{{ event.date | date: "%A %d %B %Y, %H:%M %Z" }}</h4>
<script> <script>
var event_year = {{ event.date | date: "%Y" }}; var event_year = {{ event.date | date: "%Y" }};
var event_month = {{ event.date | date: "%M" }}; var event_month = {{ event.date | date: "%-m" }};
var event_day = {{ event.date | date: "%M" }}; var event_day = {{ event.date | date: "%e" }};
var d = new Date(Date.UTC(event_year, event_month, event_day, {{ event.date | date: "%H" }}, {{ event.date | date: "%M" }})); var d = new Date(Date.UTC(event_year, event_month, event_day, {{ event.date | date: "%H" }}, {{ event.date | date: "%M" }}));
document.writeln("<p>(Local time: "+d.toTimeString()+")</p>") document.writeln("<p>(Local time: "+d.toTimeString()+")</p>")
</script> </script>

View File

@ -1,7 +1,7 @@
<nav class="container"> <nav class="container">
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom"> <header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none"> <a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
<img class="bi me-2" width="40" height="32" src="assets/img/blackmage.svg" alt="Site icon"> <img class="bi me-2" width="40" height="32" src="/assets/img/blackmage.svg" alt="Site icon">
<span class="fs-4">onFOSS-LAN hosted by {{ site.content.hosted_by_name }}</span> <span class="fs-4">onFOSS-LAN hosted by {{ site.content.hosted_by_name }}</span>
</a> </a>
@ -12,16 +12,19 @@
{% assign nav_pill = page.nav_pill %} {% assign nav_pill = page.nav_pill %}
{% endif %} {% endif %}
{% case nav_pill %} {% case nav_pill %}
{% when "tournament", "schedule", "help", "admin" %} {% when "tournament", "news", "schedule", "help", "admin" %}
{% assign home = false %} {% assign home = false %}
{% else %} {% else %}
{% assign home = true %} {% assign home = true %}
{% endcase %} {% endcase %}
<li class="nav-item"><a href="index.html" class="nav-link {% if home %}active{% endif %}" aria-current="page">Home</a></li> <li class="nav-item"><a href="/index.html" class="nav-link {% if home %}active{% endif %}" aria-current="page">Home</a></li>
<li class="nav-item"><a href="tournament.html" class="nav-link {% if nav_pill == "tournament" %}active{% endif %}">Tournament</a></li> <li class="nav-item"><a href="/news.html" class="nav-link {% if nav_pill == "news" %}active{% endif %}">News</a></li>
<li class="nav-item"><a href="schedule.html" class="nav-link {% if nav_pill == "schedule" %}active{% endif %}">Schedule</a></li> <li class="nav-item"><a href="/tournament.html" class="nav-link {% if nav_pill == "tournament" %}active{% endif %}">Tournament</a></li>
<li class="nav-item"><a href="help.html" class="nav-link {% if nav_pill == "help" %}active{% endif %}">Help</a></li> <li class="nav-item"><a href="/schedule.html" class="nav-link {% if nav_pill == "schedule" %}active{% endif %}">Schedule</a></li>
<li class="nav-item"><a href="admin.html" class="nav-link {% if nav_pill == "admin" %}active{% endif %}">Admin</a></li> <li class="nav-item"><a href="/help.html" class="nav-link {% if nav_pill == "help" %}active{% endif %}">Help</a></li>
{% unless site.content.offline %}
<li class="nav-item"><a href="/admin.html" class="nav-link {% if nav_pill == "admin" %}active{% endif %}">Admin</a></li>
{% endunless %}
</ul> </ul>
</header> </header>
</nav> </nav>

View File

@ -3,11 +3,12 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>onFOSS-LAN</title> <title>onFOSS-LAN</title>
<link rel="stylesheet" href="assets/css/main.css"> <link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="assets/css/serverstats.css"> <link rel="stylesheet" href="/assets/css/serverstats.css">
<link rel="icon" href="icon.svg" sizes="any" type="image/svg+xml"> <link rel="icon" href="/icon.svg" sizes="any" type="image/svg+xml">
<link rel="alternate" type="application/rss+xml" title="{{ site.content.domain_name }}" href="/feed.xml">
<script src="https://d3js.org/d3.v7.min.js"></script> <script src="https://d3js.org/d3.v7.min.js"></script>
<script src="js/serverstats.js"></script> <script src="/js/serverstats.js"></script>
</head> </head>
<body> <body>
{% include nav.html %} {% include nav.html %}

View File

@ -0,0 +1,8 @@
---
layout: default
nav_pill: news
---
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }} - {{ page.author }}</p>
{{ content }}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 165 KiB

View File

@ -13,7 +13,7 @@ game: armagetron
Then go to Multiplayer and then to Custom Connect. Then go to Multiplayer and then to Custom Connect.
</p> </p>
<p> <p>
Enter {{ site.content.domain_name }} in the Address field and keep the port number at 4534. Enter <span class="fw-bold">{{ site.content.domain_name }}</span> in the Address field and keep the port number at <span class="fw-bold">4534</span>.
Navigate down to Connect to Server to join. Navigate down to Connect to Server to join.
</p> </p>
<p>You should now be connected.</p> <p>You should now be connected.</p>

View File

@ -11,7 +11,7 @@ game: bzflag
<h2>Connecting</h2> <h2>Connecting</h2>
<p>Use the arrow keys to nagivate to Join Game and press &lt;Enter&gt;.</p> <p>Use the arrow keys to nagivate to Join Game and press &lt;Enter&gt;.</p>
<p> <p>
Move down to Server and type {{ site.content.domain_name }} and keep the port number at 5154. Move down to Server and type <span class="fw-bold">{{ site.content.domain_name }}</span> and keep the port number at <span class="fw-bold">5154</span>.
You can also set your Callsign here. This is how other players will see You can also set your Callsign here. This is how other players will see
your name. Then move up to Connect and press &lt;Enter&gt;.</p> your name. Then move up to Connect and press &lt;Enter&gt;.</p>
<img src="assets/img/help_bzflag.png" alt="Server join screen for Bzflag" class="img-fluid"> <img src="assets/img/help_bzflag.png" alt="Server join screen for Bzflag" class="img-fluid">

View File

@ -26,7 +26,7 @@ game: hedgewars
</p> </p>
<p> <p>
At the bottom, there is a button called &quot;Specify addres&quot;. At the bottom, there is a button called &quot;Specify addres&quot;.
Fill in {{ site.content.domain_name }} for the host and leave the port number at 46631. Fill in <span class="fw-bold">{{ site.content.domain_name }}</span> for the host and leave the port number at <span class="fw-bold">46631</span>.
</p> </p>
<img src="assets/img/help_hedgewars.png" alt="Connection settings for Hedgewars" class="img-fluid"> <img src="assets/img/help_hedgewars.png" alt="Connection settings for Hedgewars" class="img-fluid">
<p> <p>

View File

@ -12,6 +12,6 @@ game: lix
<h2>Connecting</h2> <h2>Connecting</h2>
<p>Click on &quot;Options&quot;. Then under the &quot;General&quot; tab, you can input your player name. Click on &quot;Okay&quot; to confirm.</p> <p>Click on &quot;Options&quot;. Then under the &quot;General&quot; tab, you can input your player name. Click on &quot;Okay&quot; to confirm.</p>
<p>Click on &quot;Network Game&quot;.</p> <p>Click on &quot;Network Game&quot;.</p>
<p>Under address, fill out {{ site.contents.domain_name }} and keep the port set to 22934. Then click on &quot;Okay&quot; to connect.</p> <p>Under address, fill out <span class="fw-bold">{{ site.content.domain_name }}</span> and keep the port set to <span class="fw-bold">22934</span>. Then click on &quot;Okay&quot; to connect.</p>
<p>You should see a room on the upper right. Click on that to join.</p> <p>You should see a room on the upper right. Click on that to join.</p>
<p>Choose your colour and then click &quot;Okay&quot;</p> <p>Choose your colour and then click &quot;Okay&quot;</p>

View File

@ -17,6 +17,6 @@ game: mindustry
From the main menu choose &quot;Play&quot; and then &quot;Join From the main menu choose &quot;Play&quot; and then &quot;Join
Game&quot;. You will be able to set you in-game name here. Game&quot;. You will be able to set you in-game name here.
</p> </p>
<p>To join the server, click on &quot;Add Server&quot; and type in {{ site.content.domain_name }}. When you press Ok, it will be added under &quot;Remote Servers&quot;.</p> <p>To join the server, click on &quot;Add Server&quot; and type in <span class="fw-bold">{{ site.content.domain_name }}</span>. When you press Ok, it will be added under &quot;Remote Servers&quot;.</p>
<img src="assets/img/help_mindustry.png" alt="The join screen in Mindustry with the server added" class="img-fluid"> <img src="assets/img/help_mindustry.png" alt="The join screen in Mindustry with the server added" class="img-fluid">
<p>You can then click on the server name to join.</p> <p>You can then click on the server name to join.</p>

View File

@ -11,8 +11,8 @@ game: minetest
</ul> </ul>
<h2>Connecting</h2> <h2>Connecting</h2>
<p> <p>
Under address fill in {{ site.content.domain_name }} and keep the port at Under address fill in <span class="fw-bold">{{ site.content.domain_name }}</span> and keep the port at
30000. Click on Register to set your in-game name. You can leave the password blank <span class="fw-bold">30000</span>. Click on Register to set your in-game name. You can leave the password blank
since this server will disappear after the event anyway. since this server will disappear after the event anyway.
</p> </p>
<img src="assets/img/help_minetest.png" alt="The register screen in the Minetest client" class="img-fluid"> <img src="assets/img/help_minetest.png" alt="The register screen in the Minetest client" class="img-fluid">

View File

@ -23,8 +23,8 @@ game: openhv
</p> </p>
<p> <p>
From the main menu, click on &quot;Multiplayer&quot; and then click From the main menu, click on &quot;Multiplayer&quot; and then click
on &quot;Direct IP&quot;. Fill in {{ site.content.domain_name }} and keep the port at on &quot;Direct IP&quot;. Fill in <span class="fw-bold">{{ site.content.domain_name }}</span> and keep the port at
1234. Then click on &quot;Join&quot; <span class="fw-bold">1234</span>. Then click on &quot;Join&quot;
</p> </p>
<img src="assets/img/help_openhv.png" alt="The join screen in OpenHV" class="img-fluid"> <img src="assets/img/help_openhv.png" alt="The join screen in OpenHV" class="img-fluid">
<p>You will be placed in the lobby with the other players</p> <p>You will be placed in the lobby with the other players</p>

View File

@ -46,7 +46,7 @@ game: openspades
to return to the server browser. to return to the server browser.
</p> </p>
<p> <p>
To connect to the server, type {{ site.content.domain_name }} in the input field at the To connect to the server, type <span class="fw-bold">{{ site.content.domain_name }}</span> in the input field at the
top and click on the &quot;Connect&quot; button to the right. top and click on the &quot;Connect&quot; button to the right.
</p> </p>
<img src="assets/img/help_openspades.png" alt="The join screen in OpenSpades" class="img-fluid"> <img src="assets/img/help_openspades.png" alt="The join screen in OpenSpades" class="img-fluid">

View File

@ -23,8 +23,8 @@ game: shatteredparadise
</p> </p>
<p> <p>
From the main menu, click on &quot;Multiplayer&quot; and then click From the main menu, click on &quot;Multiplayer&quot; and then click
on &quot;Direct IP&quot;. Fill in {{ site.content.domain_name }} and set the port at on &quot;Direct IP&quot;. Fill in <span class="fw-bold">{{ site.content.domain_name }}</span> and set the port at
12340. The standard port is 1234, but is already taken. Then click on &quot;Join&quot; <span class="fw-bold">12340</span>. The standard port is 1234, but is already taken. Then click on &quot;Join&quot;
</p> </p>
<img src="assets/img/help_shatteredparadise.png" alt="The join screen in Shattered Paradise" class="img-fluid"> <img src="assets/img/help_shatteredparadise.png" alt="The join screen in Shattered Paradise" class="img-fluid">
<p>You will be placed in the lobby with the other players</p> <p>You will be placed in the lobby with the other players</p>

View File

@ -19,8 +19,8 @@ game: supertuxkart
name. You don't have to set a password. name. You don't have to set a password.
</p> </p>
<p> <p>
To connect to out server, click on &quot;Enter server address&quot;. To connect to our server, click on &quot;Enter server address&quot;.
Then type in {{ site.content.domain_name }} and click on &quot;OK&quot;. Then type in <span class="fw-bold">{{ site.content.domain_name }}</span> and click on &quot;OK&quot;.
</p> </p>
<img src="assets/img/help_supertuxkart.png" alt="Entering the server address" class="img-fluid"> <img src="assets/img/help_supertuxkart.png" alt="Entering the server address" class="img-fluid">
<p> <p>

View File

@ -12,6 +12,6 @@ game: teeworlds
<p>Click on Settings and choose the Player tab. You can fill in your name so we can recognize you when you join the server. The Tee tab will also let you customize your appearance.</p> <p>Click on Settings and choose the Player tab. You can fill in your name so we can recognize you when you join the server. The Tee tab will also let you customize your appearance.</p>
<img src="assets/img/help_teeworlds_name.png" alt="Teeworlds setting for player name" class="img-fluid"> <img src="assets/img/help_teeworlds_name.png" alt="Teeworlds setting for player name" class="img-fluid">
<p>To connect to the server, got back to the main menu and click Play.</p> <p>To connect to the server, got back to the main menu and click Play.</p>
<p>At the bottom of the screen you can fill in the name of the server in the Host address field. Type {{ site.content.domain_name }} and press &lt;Enter&gt; or click Connect.</p> <p>At the bottom of the screen you can fill in the name of the server in the Host address field. Type <span class="fw-bold">{{ site.content.domain_name }}</span> and press &lt;Enter&gt; or click Connect.</p>
<img src="assets/img/help_teeworlds_server.png" alt="Joining the Teeworlds server" class="img-fluid"> <img src="assets/img/help_teeworlds_server.png" alt="Joining the Teeworlds server" class="img-fluid">
<p>You should now be connected.</p> <p>You should now be connected.</p>

View File

@ -20,6 +20,6 @@ cd dist
<p>Click on Multiplayer. You'll need to create a team before you can do anything, so click on Team and then Generate New Team and choose the type you want.</p> <p>Click on Multiplayer. You'll need to create a team before you can do anything, so click on Team and then Generate New Team and choose the type you want.</p>
<img src="assets/img/help_ufoai.png" alt="Generating a new team" class="img-fluid"> <img src="assets/img/help_ufoai.png" alt="Generating a new team" class="img-fluid">
<p>Click no the done button at the very bottom right if you are happy with it. You'll return to the multiplayer menu</p> <p>Click no the done button at the very bottom right if you are happy with it. You'll return to the multiplayer menu</p>
<p>Click on Join and type {{ site.content.domain_name }} in the field for Connect to IP and click Connect.</p> <p>Click on Join and type <span class="fw-bold">{{ site.content.domain_name }}</span> in the field for Connect to IP and click Connect.</p>
<img src="assets/img/help_ufoai_connect.png" alt="Joining the UFO:AI server" class="img-fluid"> <img src="assets/img/help_ufoai_connect.png" alt="Joining the UFO:AI server" class="img-fluid">
<p>You'll see a summary of the server. Click on Connect to connect.</p> <p>You'll see a summary of the server. Click on Connect to connect.</p>

View File

@ -16,5 +16,5 @@ game: unvanquished
</ul> </ul>
<h2>Connecting</h2> <h2>Connecting</h2>
<p>Set your in-game name by clicking on &quot;Player&quot; under &quot;Options&quot;.</p> <p>Set your in-game name by clicking on &quot;Player&quot; under &quot;Options&quot;.</p>
<p>To connect to the server, press ~ to open the console and type &quot;connect {{ site.content.domain_name }}&quot;</p> <p>To connect to the server, press ~ to open the console and type &quot;<span class="fw-bold">connect {{ site.content.domain_name }}</span>&quot;</p>
<img src="assets/img/help_unvanquished.png" alt="In-game terminal connecting to the game server" class="img-fluid"> <img src="assets/img/help_unvanquished.png" alt="In-game terminal connecting to the game server" class="img-fluid">

View File

@ -22,7 +22,7 @@ game: xonotic
</p> </p>
<p> <p>
To connect to the game server, click on the &quot;Servers&quot; To connect to the game server, click on the &quot;Servers&quot;
button. At the bottom of the screen you can fill in {{ site.content.domain_name }} in button. At the bottom of the screen you can fill in <span class="fw-bold">{{ site.content.domain_name }}</span> in
the Address field. Then press Join. the Address field. Then press Join.
</p> </p>
<img src="assets/img/help_xonotic.png" alt="Server name input in Xonotic" class="img-fluid"> <img src="assets/img/help_xonotic.png" alt="Server name input in Xonotic" class="img-fluid">

View File

@ -1,96 +1,137 @@
// Parse the Xonotic score log format and return a JSON
// The returned data contains data for the individual
// rounds as well as totals
async function xonoticGetScores() { async function xonoticGetScores() {
const data = await fetch("xonscore.txt"); const data = await fetch("xonscore.txt");
const text = await data.text(); const text = await data.text();
let stats = []; let stats = {
rounds: [],
totals: []
};
let map_name = "[unknown]"; let map_name = "[unknown]";
let duration_in_seconds = 0; let duration_in_seconds = 0;
let labels = []; let labels = [];
let round_stats = []; let round_stats = [];
text.split("\n").forEach((row) => { text.split("\n").forEach((row) => {
const fields = row.split(":"); const fields = row.split(":");
if(fields.length > 1) { if(fields.length > 1) {
const verb = fields[1] const verb = fields[1]
switch(verb) { switch(verb) {
case "scores": case "scores":
map_name = fields[2]; map_name = fields[2];
duration_in_seconds = fields[3]; duration_in_seconds = fields[3];
break; break;
case "labels": case "labels":
if(fields[2] === "player") { if(fields[2] === "player") {
labels = fields[3].split(","); labels = fields[3].split(",");
}
break;
case "player":
if(fields[2] === "see-labels") {
if(fields[5] === "spectator") {
break;
}
const split_fields = fields[3].split(",");
// Filter out the custom colours in names
const player_name = fields[6]
.replace(/\^x.../g, "")
.replace(/\^\d/g, "");
let player_stats = {name: player_name};
for(let i = 0; i < labels.length; i++) {
if(labels[i] != "") {
player_stats[labels[i]] = split_fields[i]
}
}
round_stats.push(player_stats);
}
break;
case "end":
if(round_stats.length > 0) {
round_stats = round_stats.sort((a,b) => +a["score!!"] < +b["score!!"]);
stats.rounds.push({
map_name: map_name,
duration_in_seconds: duration_in_seconds,
stats: round_stats
})
}
round_stats = [];
labels = [];
duration_in_seconds = 0;
map_name = "";
break;
} }
break;
case "player":
if(fields[2] === "see-labels") {
let split_fields = fields[3].split(",");
let player_stats = {name: fields[6]};
for(let i = 0; i < labels.length; i++) {
if(labels[i] != "") {
player_stats[labels[i]] = split_fields[i]
}
}
round_stats.push(player_stats);
}
break;
case "end":
if(round_stats.length > 0) {
stats.push({
map_name: map_name,
duration_in_seconds: duration_in_seconds,
stats: round_stats
})
}
round_stats = [];
labels = [];
duration_in_seconds = 0;
map_name = "";
break;
} }
}
}) })
let final = {};
stats.rounds.forEach((map) => {
map.stats.forEach((stat) => {
if(stat.name in final) {
final[stat.name] += +stat["score!!"]
}
else {
final[stat.name] = +stat["score!!"]
}
});
});
Object.keys(final).forEach(name => {
stats.totals.push({
name: name,
score: final[name]
})
});
stats.totals = stats.totals.sort((a,b) => a.score < b.score);
return stats; return stats;
} }
function xonoticScoreUpdate() { function xonoticScoreUpdate() {
xonoticGetScores().then((data) => { xonoticGetScores().then((data) => {
let tables = d3.select("#xonotic-results") d3.select("#xonotic-ranking")
.selectAll("table") .selectAll("li")
.data(data) .data(data.totals)
.join( .join("li")
(enter) => { .text(d => d.name + " (" + d.score + ")");
let table = enter.append("table");
let thead = table.append("thead");
thead.append("tr")
.append("th")
.attr("colspan", 5)
.text((d) => "Map name: " + d.map_name);
let headerrows = thead.append("tr");
["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => { let tables = d3.select("#xonotic-results")
headerrows.append("th").text(col); .selectAll("table")
}) .data(data.rounds)
.join(
(enter) => {
let table = enter.append("table");
let thead = table.append("thead");
thead.append("tr")
.append("th")
.attr("colspan", 5)
.text((d) => "Map name: " + d.map_name);
let headerrows = thead.append("tr");
table.append("tbody"); ["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
return table; headerrows.append("th").text(col);
}, })
(update) => {
let u = update;
u.select("th").text((d) => "Map name: " + d.map_name);
return u;
},
(exit) => exit.remove()
)
.classed("table", true);
let tbodies = tables.select('tbody'); table.append("tbody");
tbodies.selectAll("tr") return table;
.data((d) => d.stats) },
.join("tr") (update) => {
.selectAll("td") let u = update;
.data((d) => ["name", "score!!", "kills", "deaths<", "suicides<"].map((col) => d[col])) u.select("th").text((d) => "Map name: " + d.map_name);
.join("td") return u;
.text((d) => d); },
(exit) => exit.remove()
)
.classed("table", true);
let tbodies = tables.select('tbody');
tbodies.selectAll("tr")
.data((d) => d.stats)
.join("tr")
.selectAll("td")
.data((d) => ["name", "score!!", "kills", "deaths<", "suicides<"].map((col) => d[col]))
.join("td")
.text((d) => d);
}); });
} }

19
website/news.html Normal file
View File

@ -0,0 +1,19 @@
---
layout: default
nav_pill: news
---
<h1>News</h1>
{% for post in site.posts %}
<h2>{{ post.title }}</h2>
<p><strong>{{ post.date | date_to_string }} by {{ post.author }}</strong></p>
{% if forloop.first %}
{{ post.content }}
<p><a href="{{ post.url }}">Permalink</a></p>
{% else %}
{{ post.excerpt }}
<p><a href="{{ post.url }}">Read more...</a></p>
{% endif %}
{% else %}
<p>No news</p>
{% endfor %}
</ul>

View File

@ -9,6 +9,8 @@ nav_pill: schedule
<h2>Upcoming</h2> <h2>Upcoming</h2>
{% for event in upcoming %} {% for event in upcoming %}
{% include event.html %} {% include event.html %}
{% else %}
<p>No upcoming events scheduled</p>
{% endfor %} {% endfor %}
<h2>Past</h2> <h2>Past</h2>
{% for event in past %} {% for event in past %}

View File

@ -24,17 +24,20 @@ nav_pill: tournament
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</ul> </ul>
<h2>Ranking</h2>
<ol id="xonotic-ranking"></ol>
<h2>Rounds</h2>
<div id="xonotic-results"></div> <div id="xonotic-results"></div>
<script> <script>
if(typeof d3 === 'undefined') { if(typeof d3 === 'undefined') {
document.write('<p><a href="xonscore.csv">Results</a> (allow access to d3js.org for dynamic updates)</p>'); document.write('<p><a href="xonscore.txt">Results</a> (allow access to d3js.org for dynamic updates)</p>');
} }
else { else {
xonoticScoreUpdate(); xonoticScoreUpdate();
setInterval(xonoticScoreUpdate, 10000); setInterval(xonoticScoreUpdate, 10000);
} }
</script> </script>
<noscript><p><a href="xonscore.csv">Results</a> (Enable JavaScript for dynamic updates)</p></noscript> <noscript><p><a href="xonscore.txt">Results</a> (Enable JavaScript for dynamic updates)</p></noscript>
{% else %} {% else %}
<p>No tournaments have been planned for the next event.</p> <p>No tournaments have been planned for the next event.</p>
{% endif %} {% endif %}