MeshTrail is an original, Oregon Trail-inspired survival game made for short MeshCore direct messages. It is set in 1854 with a light alternate-history twist: wagon parties carry experimental Long-Range (LoRa) Aether Telegraphs linked by fort relay masts. It runs as an isolated native openHop service plugin, using the same Companion TCP integration pattern proven by MeshZork.
This is not a copy or port of the commercial Oregon Trail game. The code, simulation, events, and writing in this repository are original.
MeshTrail was created by MacKayz117.
For a beginner-friendly walkthrough, see PLAYER_GUIDE.md.
Each sender prefix gets an independent SQLite-backed wagon party. Send one command per DM:
START- create a new partyGO- travel for seven daysSTATUSorSUPPLIES- inspect the journeySHOP- view food, ammunition, and medicine prices at Independence or a fortBUY FOOD <pounds>,BUY AMMO <amount>, orBUY MEDICINE <bottles>TRADEorPASS- answer a traveler's offer for food, ammunition, or medicineFORAGE- spend one day looking for herbal medicineMEDICINE- consume one bottle to restore health and improve the next restPING- inspect galvanic cells, aerial condition, and the next relayBEACON- spend cell power to request a trail report from the prairie meshHUNT- spend ammunition and two days to gain foodREST- spend food and three days to recover healthPACE steady|strenuous|gruelingRATIONS filling|meager|bareFORD,CAULK, orFERRY- resolve a river crossing when the trail reaches oneWAITorDETOUR- respond to a bison herdCAMPorPUSH- respond to a prairie stormSPARE,REPAIR, orABANDON- resolve a broken wagonRESET- abandon the current run and start overGUIDE- return the beginner guide linkHELP- show the command listHELP <command>- explain one command, its choices, and useful examples- Choice-based hazards include bison herds, prairie storms, and wagon breakdowns
Travel events are repeatable for a given player, turn, and configured seed. MeshCore delivery retries are deduplicated so the same radio message cannot advance a party twice. The Kansas, Big Blue, South Platte, Green, Snake, and Columbia rivers interrupt travel with persistent choices; a lost or delayed reply cannot silently skip the decision. In Nebraska, travelers also join and follow the Great Platte River Road before reaching the South Platte ford.
See GAME_DESIGN.md for the historical/mesh tone and future multiplayer ideas.
Python 3.12 or newer is required.
python -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest
.venv/bin/ruff check .
python -m buildOn Windows, use .venv\Scripts\python and .venv\Scripts\pytest.
Build the wheel with python -m build. The installable file will be created in dist/ with a
name similar to openhop_meshtrail_plugin-0.5.0-py3-none-any.whl.
To install it through the openHop dashboard:
- Sign in to openHop as an administrator.
- Open Configuration, then Plugins.
- Select Wheel and choose the MeshTrail
.whlfile from thedist/directory. - Confirm the installation and wait for MeshTrail to appear in the installed plugin list.
- Enable MeshTrail if it is not already enabled. Its status should change to Running.
- Select Open on the MeshTrail card to review its player limit, inactivity timeout, and save-retention settings.
The manifest installs the plugin as openhop.meshtrail and starts the meshtrail-openhop
service. Upgrading is done the same way: build the newer wheel and install it from the Plugins
page. openHop keeps MeshTrail's data directory, so existing saved journeys remain available.
The default connection is 127.0.0.1:5003. Runtime data is stored in
$OPENHOP_PLUGIN_DATA/meshtrail.sqlite3. Configuration can be changed in the plugin's
settings page, in config.json, or with matching uppercase environment variables.
Open MeshTrail from the openHop Plugins page to set the maximum number of simultaneous players, the idle timeout, and how long inactive saves are retained. An idle player releases their active slot after the configured interval, while their SQLite-backed journey remains available until the retention period expires. The defaults are three active players, a 15-minute slot timeout, and 30 days of save retention.
MeshTrail uses port 5003 so it can coexist with a MeshZork Companion on 5002. Give each
plugin its own Companion identity; a Companion accepts only one connected TCP client.
MeshTrail is installed into openHop's existing container through the plugin manager. It does not
need a second application container. Use a plugin-capable openhop/openhop-repeater image and
keep these openHop paths on named volumes or bind mounts:
volumes:
- openhop-repeater-config:/etc/openhop_repeater
- openhop-repeater-data:/var/lib/openhop_repeaterDo not disable the container's plugin manager with OPENHOP_PLUGIN_MANAGER=0, and do not install
systemd inside the container. The openHop entrypoint supervises both the repeater and plugin
manager.
Create a dedicated Companion identity in openHop with these settings:
identities:
companions:
- name: "MeshTrail"
identity_key: "YOUR_OPENHOP_GENERATED_PRIVATE_IDENTITY_KEY"
settings:
node_name: "MeshTrail"
bind_address: "127.0.0.1"
tcp_port: 5003
tcp_timeout: 0Upload and enable the MeshTrail wheel through the openHop Plugins page. Because the plugin runs
inside the same container, 127.0.0.1:5003 is correct and the Companion port does not need to be
published by Compose. SQLite saves live below /var/lib/openhop_repeater/plugins/ and survive
container replacement when the data volume is persistent.
The repository includes tests/Dockerfile.smoke. CI builds the wheel in clean
python:3.12-slim, installs it with dependencies, checks the packaged logo, plays through the
first river crossing, and reopens the SQLite save from a new game instance.
MeshTrail publishes installable wheels as GitHub Release assets. To publish a release, first make
sure the version in pyproject.toml, openhop-plugin.json, and meshtrail_plugin/__init__.py
matches, then create and push a canonical tag such as v0.5.0. The Publish Release Wheel
workflow verifies the tag, runs the Python and Docker test suites, builds the wheel, and attaches
both the wheel and a ZIP bundle to the matching GitHub Release. It can also be rerun manually for
an existing tag from the repository's Actions page.
OpenHop's update check is catalogue-managed. Once MeshTrail is approved in the openHop plugin catalogue and installed from there, openHop compares the installed version with the catalogue's approved version and offers the update from its Plugins page. Publishing a GitHub Release alone does not make that version available through openHop; the catalogue entry must also be updated with the release wheel URL and SHA-256 checksum.
The plugin is a supervised child process. A crash or invalid game command cannot replace or stop the openHop repeater. The client reconnects with bounded backoff if the Companion TCP connection is interrupted.
