Compare commits

...

30 Commits

Author SHA1 Message Date
Florian Obser 5275adb20c Update to new / tweaked way of doing the nsd update. 2024-04-14 18:59:44 +02:00
Florian Obser f29d88e845 Flip read-only-mode and text-mode to make it work with view-mode. 2024-03-25 16:32:01 +01:00
Florian Obser b510145d24 crank copyright 2024-03-22 07:58:29 +01:00
Florian Obser 3ee4c6146c Hook up SingleFile 2024-03-20 21:26:11 +01:00
Florian Obser 4298004b30 Write about SingleFile 2024-03-20 21:24:46 +01:00
Florian Obser 46d247c0e6 We need the full account name after recent mastodon update. 2024-02-03 09:51:35 +01:00
Florian Obser b697286ade hook up openttd article 2024-01-13 15:41:53 +01:00
Florian Obser d0b14e6b30 Editorial changes. 2024-01-13 15:40:43 +01:00
Florian Obser 6431d175c1 epilogue 2024-01-13 15:12:38 +01:00
Florian Obser 95132894e3 link to lugnutsk srnw video 2024-01-13 15:12:14 +01:00
Florian Obser 20b5971137 Bonus: pbs prio 2024-01-13 15:04:52 +01:00
Florian Obser e2f975ef05 SRNW signalling 2024-01-13 14:39:58 +01:00
Florian Obser d3f110941a Fix headline 2024-01-13 14:22:51 +01:00
Florian Obser de091f557b Fix preview image names. 2024-01-13 12:46:09 +01:00
Florian Obser 8d2d3a4d3a Train orders 2024-01-13 12:44:23 +01:00
Florian Obser 3c63ee0b52 typo 2024-01-13 09:28:52 +01:00
Florian Obser a8efc6b2e8 Station construction 2024-01-13 09:27:55 +01:00
Florian Obser 1a0d2846ab Fix footnotes 2024-01-13 08:46:18 +01:00
Florian Obser d30ba8ca8e city layout 2024-01-13 08:44:52 +01:00
Florian Obser 62865f9bcf Flesh out SRNW section. 2024-01-12 19:53:59 +01:00
Florian Obser ee4976b816 fix previous 2024-01-12 19:41:50 +01:00
Florian Obser 44ae2024d1 Use small preview image. 2024-01-12 19:40:27 +01:00
Florian Obser 8f4064baee First stab at srnw 2024-01-12 19:14:00 +01:00
Florian Obser afd22dd2e4 We don't track doc/CREDITS. 2023-11-30 09:08:31 +01:00
Florian Obser 14f17c6b04 Add missing continuation in shell code. 2023-11-30 08:39:48 +01:00
Florian Obser 233abcdee2 Fix GitHub link.
Pointed out by Martin Schröder, thanks!
2023-11-25 13:04:52 +01:00
Florian Obser f294f171b5 We can just reboot since we ignore errors. 2023-10-13 15:37:15 +02:00
Florian Obser 066f90e34b We need to ignore errors. 2023-10-06 16:46:22 +02:00
Florian Obser c589c89f60 Mastodon Backup 2023-07-26 13:10:41 +02:00
Florian Obser e5933409ef Adjust ignore list, update to newer nsd version while here. 2023-06-07 13:10:57 +02:00
34 changed files with 455 additions and 15 deletions

123
SingleFile.org Normal file
View File

@ -0,0 +1,123 @@
#+TITLE: SingleFile
#+DATE: 2024-03-20
* Prologue
I am using the [[https://en.wikipedia.org/wiki/Zettelkasten#Use_in_personal_knowledge_management][Zettelkasten]] methodology for personal knowledge
management, with [[https://www.orgroam.com/][Org-roam]] to implement it.
While the Internet does not forget things in general, it might be
difficult to find things again. Maybe someone published some
information in a GitHub gist or has their whole blog there.
Suddenly GitHub falls out of favour because it got bought by an
evilcorp and information disappears.
For those reasons I store a link to the information directly, a link
to the [[https://web.archive.org/][Wayback Machine]] and a local copy. My Zettelkasten and all
references, including a local copy, are stored in git.
* SingleFile
[[https://github.com/gildas-lormeau/SingleFile][SingleFile]] is a Firefox[fn::Other browsers are supported as well, I
just think Firefox is the least-evil one.] extension to save a website,
including images and css, into a single HTML file. It's perfect for
personal archival purposes. When run as a plugin it will save the page
as it is currently rendered. For example dismissed cookie banners will
not be part of the safes page.
The downside is that it's some semi-manual process to get the backup
into the Zettelkasten note.
* SingleFile-CLI
There is also a [[https://github.com/gildas-lormeau/single-file-cli][CLI]] version, like all modern stuff it runs in
docker. Of course I do not have docker on OpenBSD, nor the alternative
podman.
So I setup a Fedora VM, installed podman and run singlefile-cli via
ssh. On the Fedora VM I use this wrapper:
#+begin_src sh
#! /bin/sh
set -e
content=$(podman run --privileged -u 0:0 singlefile "$@")
now=$(date --iso-8601=seconds -u)
title=$(echo ${content} | /home/florian/.cargo/bin/htmlq --text title | \
awk '{$1=$1};1' | \
head -1 | tr -d '\n' | tr -c '[:alnum:]' '_' | cut -c -128)
fn="/tmp/${title}_${now}.html"
echo ${content} > ${fn}
echo $fn
#+end_src
It fetches a copy of the website, uses [[https://github.com/mgdm/htmlq][htmlq]] to extract the title,
removes special characters and saves the page in ~/tmp~. It then spits
out the file-name of the backup.
On my laptop I have this script:
#+begin_src sh
#! /bin/sh
set -e
fn=$(ssh fedora bin/singlefile "$@")
bn=$(basename ${fn})
scp fedora:${fn} .
open ${bn}
#+end_src
This causes the Fedora VM to fetch a backup of the website and then
copies it over and stores it in the current working directory. Finally
it opens it in the browser for inspection.
* org-cliplink
We still do not have links stored in the Zettelkasten note.
For that I use [[https://github.com/rexim/org-cliplink][org-cliplink]] to insert org mode links from the
clipboard.
A bit of elisp code massages the link text to add "Archive: " or
"Local: " in front of the title. It also changes the URL for the local
backup to have it relative so that it works correctly no matter where
the git repo with the Zettelkasten is checked out.
#+begin_src elisp
(use-package org-cliplink
:config
(defun custom-org-cliplink ()
(interactive)
(org-cliplink-insert-transformed-title
(org-cliplink-clipboard-content) ;take the URL from the CLIPBOARD
(lambda (url title)
(let* ((parsed-url (url-generic-parse-url url)) ;parse the url
(turl
(cond
;; if type is file make the url relative to zettelkasten
((string= (url-type parsed-url) "file")
(url-unhex-string (replace-regexp-in-string "\\(.+\\)\/zettelkasten\/\\(.+\\)" "file:\\2" url)))
;; otherwise keep the original url
(t url)))
(ttitle
(cond
;; if type is file, add Local: to title
((string= (url-type parsed-url) "file")
(replace-regexp-in-string "\\(.+\\)" "Local: \\1" title))
;; otherwise keep the original title
(t title))))
;; forward to the default org-cliplink transformer
(org-cliplink-org-mode-link-transformer turl ttitle)))))
:custom
(org-cliplink-title-replacements
'(("https://github.com/.+/?"
("\\(.*\\) · \\(?:Issue\\|Pull Request\\) #\\([0-9]+\\) · \\(.*\\) · GitHub" "\\3#\\2 \\1"))
("https://twitter.com/.+/status/[[:digit:]]+/?"
(".+ on Twitter: \\(.+\\)" "\\1"))
("https://web.archive.org/.+/?"
("\\(.+\\)" "Archive: \\1"))))
:bind (:map org-mode-map
("C-c C-S-L" . custom-org-cliplink)))
#+end_src
* Epilogue
I only recently added singlefile-cli to my work-flow, so far it is a
big improvement. Time will tell if the backups are cluttered with
banners and I have to go back to semi-manual mode.

View File

@ -591,7 +591,7 @@ We set it to a very low priority[fn:: Remember, a high priority
dhcpleased(8) configures when we move to an IPv4 enabled network.
We then need to configure address family translation in pf(4) when we
detect /NAT64/ being present. This is were [[https://github.com/fobser/gelatod/][gelatod(8)]] comes in. It is
detect /NAT64/ being present. This is were [[https://codeberg.org/fobser/gelatod][gelatod(8)]] comes in. It is
a Customer-side transLATor (/CLAT/) configuration daemon[fn::If you
squint just right, gelato kinda sounds like clat[fn::Again, I really
really should be prohibited from naming things.].]. /CLAT/ is what

View File

@ -50,8 +50,8 @@ comes down to opening the correct file. So we can copy the code of
(if (listp value)
(mapcar 'pop-to-buffer-same-window (nreverse value))
(pop-to-buffer-same-window value))
(read-only-mode)
(text-mode)))
(text-mode)
(read-only-mode)))
;; RFCs are stored in 'in-notes/'
(defun ietf-rfc (filename &optional wildcards)
@ -66,10 +66,15 @@ comes down to opening the correct file. So we can copy the code of
(if (listp value)
(mapcar 'pop-to-buffer-same-window (nreverse value))
(pop-to-buffer-same-window value))
(read-only-mode)
(text-mode)))
(text-mode)
(read-only-mode)))
#+end_src
*Update 2024-03-25*: Flipping the order of ~(text-mode)~ and
~(read-only-mode)~ so that ~(read-only-mode)~ gets activated last
makes it work correctly with ~view-mode~ if that mode is automatically
activated by ~(setq view-read-only t)~ on read-only buffers.
Setting a global key binding lets us open RFCs and drafts from
anywhere within Emacs:
#+begin_src emacs-lisp

View File

@ -7,6 +7,9 @@
+ [[https://www.linkedin.com/in/florian-obser-75900383][Linkedin]]
* Meditations
- [[file:SingleFile.org][2024-03-20: SingleFile]]
- [[file:openttd-srnw.org][2024-01-13: OpenTTD Self Regulating Networks]]
- [[file:mastodon-backup.org][2023-07-26: Mastodon Backup]]
- [[file:emacs-ietf.org][2023-04-05: Emacs IETF]]
- [[file:dynamic_host_configuration_please.org][2023-03-07: Dynamic host configuration, please]]
- [[file:privsep.org][2023-02-19: Privilege drop, privilege separation, and restricted-service operating mode in OpenBSD]]

103
mastodon-backup.org Normal file
View File

@ -0,0 +1,103 @@
#+TITLE: Mastodon Backup
#+DATE: 2023-07-26
* Prologue
People on the Fediverse like to point out how you have to backup your
data regularly in case of a catastrophic failure effecting your
instance, the host of your instance, the data centre of your instance
or maybe your admin. Heck, even a catastrophic failure effecting an
admin of /another/ instance might make you wish you had a backup of
your follows list[fn::If a remote admin decides to de-federate your
instance it will sever all your connections with people on that
instance.].
Remembering to make a backup manually is already difficult
enough[fn::My last manual backup was over a year old.], but then you
also need to remember *how* to make that backup...
* Manual Backups
Got to "App Settings". You do not know where "App Settings" are? I
know the feeling... They are behind the three cogs on the top
left. Navigate to "Import and export". Click "Data export". Click the
"CSV" link. Click the other "CSV" link. Click the other other "CSV"
link. You have now downloaded your "follows", "muted" and "blocked"
accounts lists.
* Automatic Backups
I have recently discovered [[https://toot.bezdomni.net/introduction.html][toot - Mastodon CLI client]] which can output
a list of your follows and people following you. I have [[https://github.com/ihabunek/toot/pull/390][contributed
code for "muted" and "blocked" commands]] which got accepted and
released in version 0.38.
We first need to authenticate to our instance by running ~toot
login~. This is only needed once. For more information [[https://toot.bezdomni.net/usage.html][see the
official documentation]].
I am running the following script from cron once a day:
#+begin_src shell
#! /bin/ksh
ACCOUNT=@florian@bsd.network
INSTANCE=bsd.network
BACKUPDIR=/home/mastodonbackup/backup
set -e
set -o pipefail
exit_if_nonzero_or_stderr() {
(
set -o pipefail
{ "$@" 1>&3 ;} 2>&1 | {
if IFS= read -r line; then
printf "%s\n" "$line"
cat
exit 1
fi
} >&2
) 3>&1
}
exit_if_nonzero_or_stderr /usr/local/bin/toot muted | \
awk '$2 !~ /^@.*@/ {print $2 "@'${INSTANCE}'"; next} {print $2}' \
> ${BACKUPDIR}/muted.new
mv ${BACKUPDIR}/muted{.new,}
exit_if_nonzero_or_stderr /usr/local/bin/toot blocked | \
awk '$2 !~ /^@.*@/ {print $2 "@'${INSTANCE}'"; next} {print $2}' \
> ${BACKUPDIR}/blocked.new
mv ${BACKUPDIR}/blocked{.new,}
exit_if_nonzero_or_stderr /usr/local/bin/toot following ${ACCOUNT} | \
awk '$2 !~ /^@.*@/ {print $2 "@'${INSTANCE}'"; next} {print $2}' \
> ${BACKUPDIR}/following.new
mv ${BACKUPDIR}/following{.new,}
exit_if_nonzero_or_stderr /usr/local/bin/toot followers ${ACCOUNT} | \
awk '$2 !~ /^@.*@/ {print $2 "@'${INSTANCE}'"; next} {print $2}' \
> ${BACKUPDIR}/followers.new
mv ${BACKUPDIR}/followers{.new,}
#+end_src
~toot~ outputs accounts from the local instance without
/@instance/. ~awk(1)~ checks for the existence of two /@/ characters
and if they are not present outputs /@instance@/ after the account
name.
Unfortunately ~toot~ always exits with 0, even if there is an error so
we need to check if there is some output on =stderr= so that we do not
replace our backup with empty files. For that I copy-pasted
=exit_if_nonzero_or_stderr= from [[https://stackoverflow.com/a/61468182][stackoverflow]] like a pro.
My crontab entry looks like this:
#+begin_src crontab
~ 9 * * * -sn su -s /bin/sh mastodonbackup -c /home/mastodonbackup/backup.sh
#+end_src
=-sn= ensures that the script is only run once and that no mail is
sent after a successful run. See [[https://man.openbsd.org/crontab.5][crontab(5)]] for details.
* Epilogue
I have automated backing up the most important lists from my mastodon
account. My mastodon account is running on somebody else's
computer. The backup data is written as text files on a system that I
control. That system is hooked up to my standard backup solution to
have daily, multiple-redundant backups.
I expire my toots after 90 days using [[https://ephemetoot.hugh.run/][ephemetoot]]. I have configured it
to save the toots and media before deleting them from my account.

View File

@ -28,9 +28,12 @@ I'll just leave this here...
- name: reboot and wait for host to return
block:
- name: schedule reboot in 1 minute
- name: reboot
ansible.builtin.command:
cmd: 'shutdown -r +1'
cmd: reboot
ignore_errors: yes
async: 3600
poll: 0
- name: wait for ssh to go away
ansible.builtin.wait_for:
host: '{{ (ansible_ssh_host|default(ansible_host))|default(inventory_hostname) }}'

View File

@ -8,13 +8,13 @@ upstream.
git clone from the upstream repository on [[https://github.com/NLnetLabs/nsd][github]].
#+begin_src shell
git pull
git diff NSD_4_3_6_REL..NSD_4_3_7_REL . ':!.cirrus.yml' ':!tpkg/*' \
':!contrib/*' ':!compat/' ':!README.md' ':!.gitignore' \
':!.buildkite/*' ':!makedist.sh' > ~/nsd_4.3.7_upstream.diff
git diff NSD_4_6_1_REL..NSD_4_7_0_REL . ':!.cirrus.yml' ':!tpkg/*' \
':!contrib/*' ':!compat/' ':!.gitignore' ':!doc/README.svn' \
':!doc/CREDITS' \
':!.buildkite/*' ':!makedist.sh' > ~/nsd_4.7.0_upstream.diff
cd /usr/src/usr.sbin/nsd
patch -Ep0 < ~/nsd_4.3.7_upstream.diff
autoheader-2.69
autoconf-2.69
patch -Ep0 < ~/nsd_4.7.0_upstream.diff
autoconf-2.71
make -f Makefile.bsd-wrapper obj
make -f Makefile.bsd-wrapper clean
make -f Makefile.bsd-wrapper -j4
@ -22,7 +22,7 @@ git clone from the upstream repository on [[https://github.com/NLnetLabs/nsd][gi
We also need to update the version numbers in the man pages. For that
we download the release tar ball and generate a diff:
#+begin_src shell
diff -ru . /home/florian/nsd-4.3.7/ | fgrep -v Only > sync.diff
diff -bru . /home/florian/nsd-4.7.0/ | fgrep -v Only > sync.diff
#+end_src
The diff then needs to be partially applied, some changes are
intentional.

203
openttd-srnw.org Normal file
View File

@ -0,0 +1,203 @@
#+TITLE: OpenTTD Self Regulating Networks
#+DATE: 2024-01-13
[[file:openttd-srnw/srnw_head.png]]
* Prologue
Every other year or so I decide to play a game or ten of
[[https://openttd.org/][OpenTTD]]. Unfortunately I don't remember most of the things I figured
out in the past so I have to start from first principles.
In this case, first principles means reading the [[https://wiki.openttdcoop.org/Main_Page][openttdcoop Wiki]]
[fn::which is quite dense] and watching a bunch of [[https://www.youtube.com/@LugnutsK][LugnutsK]]
videos. For the topic at hand I would suggest
[[https://www.youtube.com/watch?v=ZVtszocBmiY][Advanced OpenTTD - Self-Regulating Networks]].
* Self Regulating Passenger Network
The idea of a self regulating passenger network is to grow a city and
transport as many passengers out of the city as possible with the
least amount of train orders.
openttdcoop calls it [[http://wiki.openttdcoop.org/Gametype:ICE_SBahn][Gametype:ICE SBahn]] / [[http://wiki.openttdcoop.org/Self-regulating_SBahn][Self-regulating SBahn]].
The idea is to have (SBahn) stations spread throughout the city that
collect passengers. Once a train is fully loaded with passengers, it
drives outside of the city to a transfer (ICE) station and transfers
passengers to a waiting train that then transports the passengers to a
far away city to make money.
We do not want to deal with each station individually but run the
pick-up trains in a loop that automatically visits a station with
a full load of passengers available.
To make all of this work we have:
1. Inner-city SBahn stations
2. Outside-city waiting loop for the pick-up trains
3. Outside-city exit track to the transfer / ICE station
4. Outside-city transfer / ICE station
5. Injection mechanism from the ICE station to the waiting loop.
[[file:openttd-srnw/overview.png][file:openttd-srnw/overview_small.png]]
The pick-up trains have two orders:
1. Go to transfer / ICE station and transfer passengers.
2. Go to inject way-point.
The inject way-point leads to the waiting loop. From there the only
way to reach the transfer station is through any of the SBahn
stations. We have to arrange the SBahn stations in a way that they are
only accessible when there is a full load of passengers available.
* City Layout
For maximum growth and ease of putting train stations into the city we
are using a 3x3 road grid. A spiral would be even better for city
growth but it is annoying to put train stations into a spiral without
disrupting the roads too much and creating dead-ends. Dead-ends are
very bad for town growth.
We need to find a balance between station size[fn::One constraint here
is how much space the station takes away from the city to build houses.],
city coverage, and needed capacity at the transfer station. Using spread
stations covering a 5x5 block[fn::A block is a 3x3 road grid.] and
having six of those works fairly well. To be able to fit tunnels in we
put two in a line and have three lines[fn::Three in a line would also
leave enough space for tunnels. But then the waiting loop might become
too big and it takes to long to try all the SBahn stations. This is
especially a problem once the city is big and produces lots of
passengers.]. This results in a city grid of 13x8 blocks.
[[file:openttd-srnw/city-layout.png][file:openttd-srnw/city-layout_small.png]]
* Station Construction
We are building a spread station in a 3x3 block by putting a city
station in each of the corners of the block. Holding =ctrl= while
placing the building opens the "Join station" menu and we select an
existing station.
[[file:openttd-srnw/spread-station.png][file:openttd-srnw/spread-station_small.png]]
The coverage of the station is not perfect but some of these parts
will later be filled by the tracks of the train station. Note that the
station also covers a block outside of the road grid, so each spread
station covers a 5x5 block. This is important when putting in adjacent
stations to not have them overlap.
[[file:openttd-srnw/station-coverage.png][file:openttd-srnw/station-coverage_small.png]]
For the rail network we dig two trenches outside of the city. Tunnels
to those will connect the station to the waiting loop on one side of
the city and the exit to the transfer station on the other side of the
city.
We then remove some roads and the crossings[fn::This ensures that we
can dig a complete hole, we will put the roads back in later.] on one
side of the block and dig a 7x2 hole for the train tracks.
[[file:openttd-srnw/station-digging.png][file:openttd-srnw/station-digging_small.png]]
Next: Tunnels, tracks, signal, a way-point, and a train depot.
[[file:openttd-srnw/station-tunnels-and-tracks.png][file:openttd-srnw/station-tunnels-and-tracks_small.png]]
We then place a two platform, length five station, making sure we join
it with the existing spread station.
[[file:openttd-srnw/station-placing-tracks.png][file:openttd-srnw/station-placing-tracks_small.png]]
The finished station looks like this:
[[file:openttd-srnw/station-anotation.png][file:openttd-srnw/station-anotation_small.png]]
We are going to put a dummy train onto the dummy track to pick up
passengers and making sure a full load is available when a pick-up
train arrives. We do not place exit signals at the station. When a
dummy train is inside the station it blocks the whole station due to
the crossing tracks at the end of the station. The way-point is going
to be used to open the station for the pick-up trains.
* Train Orders
** Dummy Trains
We create a dummy train per station. These collect passengers and
block the station for the pick-up trains. Once a full load of
passengers has been collected the dummy train unloads them and
unblocks the station. Now a full load of passengers is available for
the pick-up trains.
We make the trains length four so that it can drive around in the
station itself, which has length five. We are using "near end" and "far
end" orders:
1. Go to near end of the station and full load
2. Go to far end of the station and transfer
3. Go to the way-point after the station.
Step three is what unblocks the station. Once the train has left the
depot we have to remove the track right in front of it so that the
dummy train cannot re-enter the depot. Alternatively we could put the
depot right after the way-point and delete it after the train left it.
[[file:openttd-srnw/dummy-train-orders.png][file:openttd-srnw/dummy-train-orders_small.png]]
** Pick-up Trains
The pick-up trains have two orders:
1. Go via INJECT way-point
2. Go to transfer station and transfer.
Unfortunately OpenTTD will create implicit orders every time the train
passes through one of the SBahn stations. To prevent this we add a
"Jump to order 1" instruction and then fill up the orders with an
unreachable way-point. A train can only have 255 orders. Once the
order list is full no implicit orders can be created.
[[file:openttd-srnw/pick-up-train-orders.png][file:openttd-srnw/pick-up-train-orders_small.png]]
* Self Regulating Network Signalling
The interesting bit happens once the trains passed the INJECT
way-point. They are now inside of the waiting loop and try to get
to the transfer station. This is only possible through one of the
SBahn stations.
When a train reaches the tunnel entrance to an SBahn station it has
two choices, either continue in the waiting loop or enter the station.
If a train is already in the waiting bay of that station we want our
train in the waiting loop to continue and try the next station. We put
two-way block signals at the tunnel entrance which turns red when the
waiting bay is occupied by a train. OpenTTD's path finder treats a red
two-way signal as a dead-end[fn::This is only true if
=yapf.rail_firstred_twoway_eol= is =True=. This is the default in
OpenTTD 13.]. It has an infinite penalty and any other
path will be better. Our train continues. This is the first block
signal in the picture below.
At our second SBahn entrance the waiting bay is free and the block
signal shows green, so a train should enter the waiting bay towards
the station. However, the path finder sees that the path goes through
a station. Going through a station incurs a penalty for that path and
it might so happen that the path continuing in the waiting loop is
considered better, our train would not enter the waiting bay.
We need to add a penalty to the waiting loop path to make the path
through the station look better. We do this by adding a few reversed
path signals after the choice.
[[file:openttd-srnw/srnw-signalling.png][file:openttd-srnw/srnw-signalling_small.png]]
* Bonus: Path Based Signal Priority Merge
The [[https://wiki.openttdcoop.org/Priorities#PBS_prio][Priority - #openttdcoop wiki]] article shows how to construct a
priority merge using path based signals. Since I will likely forget it
and the traditional priorities are slightly more difficult to build I
put a note here.
The way this works is that the tracks coloured in red form one big
signal block that reaches all the way to the merger at the front. Once
the mainline train enters this block the entry signal for the merging
train turns red and the merging train has to wait for the mainline
train to clear the block.
[[file:openttd-srnw/pbs-prio.png][file:openttd-srnw/pbs-prio_small.png]]
* Epilogue
After many iterations I came up with this city layout and station
design. It is probably not the best one and different trade-offs can
be made. The most fun in OpenTTD is to figure these things out and not
just copying a design from somewhere. When I come back to playing
OpenTTD in a few years I can start from this and try to improve on
this and do not have to re-discover all this the hard way.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

BIN
openttd-srnw/overview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

BIN
openttd-srnw/pbs-prio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 KiB

BIN
openttd-srnw/srnw_head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 KiB

View File

@ -52,7 +52,7 @@
:time-stamp-file: nil
:html-postamble "<p class=\"date\">Published: %d</p>
<hr /><footer><nav><a href=\"/\">&lt; Home</a></nav>
Copyright &copy; 2014 - 2023 Florian Obser. All rights reserved.
Copyright &copy; 2014 - 2024 Florian Obser. All rights reserved.
</footer>"
:html-head-include-default-style: nil
:html-head "<link rel=\"stylesheet\" href=\"simple.min.css\" type=\"text/css\"/>