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/
website/_sass/bootstrap/
website/_site/
website/config.yml
website/_config.yml
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
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.
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.
```

View File

@ -67,7 +67,7 @@ apt install --assume-yes \
fuse g++ gcc curl firewalld automake autoconf libtool \
libcurl3-dev libc-ares-dev zlib1g-dev libncurses-dev make python3-aiohttp \
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
if ! getent passwd ${systemuser}; then

View File

@ -39,13 +39,38 @@ if [ -d "$(dirname "$0")"/../website/_sass/bootstrap ]; then
fi
mv ${TMPDIR:-/tmp}/bootstrap/bootstrap-5.2.3/scss ${webroot}/_sass/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
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:
hosted_by_name: "${HOSTEDBYNAME}"
domain_name: "${DOMAINNAME}"
offline: true
ssl: true
ssl: ${ssl}
md5password: "$(echo -n "${systempassword}" | md5sum | cut -d' ' -f1)"
defaults:
-
scope:
path: ""
type: "posts"
values:
layout: "post"
plugins:
- jekyll-feed
EOF
jekyll build --source ${webroot} --destination ${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
if [ x"$NOSSL" = "x" ] || [ $NOSSL -ne 1 ]; then
ssl="true"
s_for_https="s"
certbot -n --nginx -d ${DOMAINNAME} -d www.${DOMAINNAME} --agree-tos -m "${letsencryptemail}"
else
s_for_https=""
ssl="false"
fi
@ -41,12 +43,28 @@ fi
mv ${TMPDIR:-/tmp}/bootstrap/bootstrap-5.2.3/scss "$(dirname "$0")"/../website/_sass/bootstrap
rm -r ${TMPDIR:-/tmp}/bootstrap.zip ${TMPDIR:-/tmp}/bootstrap
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:
hosted_by_name: "${HOSTEDBYNAME}"
domain_name: "${DOMAINNAME}"
offline: false
ssl: ${ssl}
md5password: "$(echo -n "${systempassword}" | md5sum | cut -d' ' -f1)"
defaults:
-
scope:
path: ""
type: "posts"
values:
layout: "post"
plugins:
- jekyll-feed
EOF
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>
<script>
var event_year = {{ event.date | date: "%Y" }};
var event_month = {{ event.date | date: "%M" }};
var event_day = {{ event.date | date: "%M" }};
var event_month = {{ 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" }}));
document.writeln("<p>(Local time: "+d.toTimeString()+")</p>")
</script>

View File

@ -1,7 +1,7 @@
<nav class="container">
<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">
<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>
</a>
@ -12,16 +12,19 @@
{% assign nav_pill = page.nav_pill %}
{% endif %}
{% case nav_pill %}
{% when "tournament", "schedule", "help", "admin" %}
{% when "tournament", "news", "schedule", "help", "admin" %}
{% assign home = false %}
{% else %}
{% assign home = true %}
{% 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="tournament.html" class="nav-link {% if nav_pill == "tournament" %}active{% endif %}">Tournament</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="help.html" class="nav-link {% if nav_pill == "help" %}active{% endif %}">Help</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="/index.html" class="nav-link {% if home %}active{% endif %}" aria-current="page">Home</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="/tournament.html" class="nav-link {% if nav_pill == "tournament" %}active{% endif %}">Tournament</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="/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>
</header>
</nav>

View File

@ -3,11 +3,12 @@
<head>
<meta charset="utf-8">
<title>onFOSS-LAN</title>
<link rel="stylesheet" href="assets/css/main.css">
<link rel="stylesheet" href="assets/css/serverstats.css">
<link rel="icon" href="icon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/css/serverstats.css">
<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="js/serverstats.js"></script>
<script src="/js/serverstats.js"></script>
</head>
<body>
{% 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.
</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.
</p>
<p>You should now be connected.</p>

View File

@ -11,7 +11,7 @@ game: bzflag
<h2>Connecting</h2>
<p>Use the arrow keys to nagivate to Join Game and press &lt;Enter&gt;.</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
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">

View File

@ -26,7 +26,7 @@ game: hedgewars
</p>
<p>
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>
<img src="assets/img/help_hedgewars.png" alt="Connection settings for Hedgewars" class="img-fluid">
<p>

View File

@ -12,6 +12,6 @@ game: lix
<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;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>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
Game&quot;. You will be able to set you in-game name here.
</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">
<p>You can then click on the server name to join.</p>

View File

@ -11,8 +11,8 @@ game: minetest
</ul>
<h2>Connecting</h2>
<p>
Under address fill in {{ site.content.domain_name }} and keep the port at
30000. Click on Register to set your in-game name. You can leave the password blank
Under address fill in <span class="fw-bold">{{ site.content.domain_name }}</span> and keep the port at
<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.
</p>
<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>
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
1234. Then click on &quot;Join&quot;
on &quot;Direct IP&quot;. Fill in <span class="fw-bold">{{ site.content.domain_name }}</span> and keep the port at
<span class="fw-bold">1234</span>. Then click on &quot;Join&quot;
</p>
<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>

View File

@ -46,7 +46,7 @@ game: openspades
to return to the server browser.
</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.
</p>
<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>
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
12340. The standard port is 1234, but is already taken. Then click on &quot;Join&quot;
on &quot;Direct IP&quot;. Fill in <span class="fw-bold">{{ site.content.domain_name }}</span> and set the port at
<span class="fw-bold">12340</span>. The standard port is 1234, but is already taken. Then click on &quot;Join&quot;
</p>
<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>

View File

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

View File

@ -16,5 +16,5 @@ game: unvanquished
</ul>
<h2>Connecting</h2>
<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">

View File

@ -22,7 +22,7 @@ game: xonotic
</p>
<p>
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.
</p>
<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() {
const data = await fetch("xonscore.txt");
const text = await data.text();
let stats = [];
let stats = {
rounds: [],
totals: []
};
let map_name = "[unknown]";
let duration_in_seconds = 0;
let labels = [];
let round_stats = [];
text.split("\n").forEach((row) => {
const fields = row.split(":");
if(fields.length > 1) {
const verb = fields[1]
switch(verb) {
case "scores":
map_name = fields[2];
duration_in_seconds = fields[3];
break;
case "labels":
if(fields[2] === "player") {
labels = fields[3].split(",");
const fields = row.split(":");
if(fields.length > 1) {
const verb = fields[1]
switch(verb) {
case "scores":
map_name = fields[2];
duration_in_seconds = fields[3];
break;
case "labels":
if(fields[2] === "player") {
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;
}
function xonoticScoreUpdate() {
xonoticGetScores().then((data) => {
let tables = d3.select("#xonotic-results")
.selectAll("table")
.data(data)
.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");
d3.select("#xonotic-ranking")
.selectAll("li")
.data(data.totals)
.join("li")
.text(d => d.name + " (" + d.score + ")");
["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
headerrows.append("th").text(col);
})
let tables = d3.select("#xonotic-results")
.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");
return table;
},
(update) => {
let u = update;
u.select("th").text((d) => "Map name: " + d.map_name);
return u;
},
(exit) => exit.remove()
)
.classed("table", true);
["Name", "Score", "Kills", "Deaths", "Suicides"].forEach((col) => {
headerrows.append("th").text(col);
})
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);
table.append("tbody");
return table;
},
(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');
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>
{% for event in upcoming %}
{% include event.html %}
{% else %}
<p>No upcoming events scheduled</p>
{% endfor %}
<h2>Past</h2>
{% for event in past %}

View File

@ -24,17 +24,20 @@ nav_pill: tournament
{% endif %}
{% endfor %}
</ul>
<h2>Ranking</h2>
<ol id="xonotic-ranking"></ol>
<h2>Rounds</h2>
<div id="xonotic-results"></div>
<script>
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 {
xonoticScoreUpdate();
setInterval(xonoticScoreUpdate, 10000);
}
</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 %}
<p>No tournaments have been planned for the next event.</p>
{% endif %}