- Elixir 99.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
build / image (push) Successful in 27s
Reviewed-on: #225 |
||
| .forgejo/workflows | ||
| config | ||
| dev | ||
| lib | ||
| priv | ||
| scripts | ||
| test | ||
| .dialyzer_ignore.exs | ||
| .dockerignore | ||
| .formatter.exs | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| mix.exs | ||
| mix.lock | ||
| README.md | ||
About
Black Lobster is a RuneScape server emulator for the 468 client protocol — the game as it stood on 10 August 2007 (the date of the OpenRS2 #633 cache it runs against). It's a hobby project and very much a work in progress. There are no other 468 private servers to crib from, so most of the protocol, cache parsing, and content has been reverse-engineered from the original client and cache by hand.
The server is Elixir/OTP and leans hard on the BEAM: a process per player and per NPC, ETS for the hot path, and a 600ms world tick. A fair amount already works — banking, player-to-player trading, a chunk of the skilling and combat systems, and a goal-driven bot framework that doubles as a load-test harness and runs a little self-sustaining in-game economy. Plenty is still half-built or rough around the edges. The companion game client is the original 468 client, deobfuscated and converted to Kotlin.
Note
Canonical source:
git.dunk.works/BlackLobster/Serveris the source of truth. Anything you find elsewhere is a mirror. The client lives next door atBlackLobster/Client, and the v1 roadmap is in the forge milestones. Found a bug or have a fix? Open an issue on the forge or email a patch to sickday@sickday.sh.
Requirements
elixir>=1.18(with a matchingErlang/OTP—27+is fine)bzip2/libbz2headers — the cache decompression NIF needs them- A database, either:
- SQLite (the default) — single file, nothing extra to run
- PostgreSQL
14+— setBL_DATABASE_ADAPTER=postgres. The adapter is picked at compile time, so recompile if you switch.
- A 468 game cache — you bring your own (see below). Nothing is bundled.
Game cache
This repo ships no cache — it's copyrighted game data that isn't ours to hand out. Grab your own 468 cache (the matching revision is OpenRS2 #633, dated 2007-08-10) and drop it where the server looks for it. By default that's ./cache/468/; point BL_CACHE_PATH at a different parent directory if you like. The server serves cache data to the client over JS5 on the game port, so no separate file server is involved.
Running it
- Drop a
config/.env.dev.exsfile with whatever env you need.config/example.exsis a decent starting point:
System.put_env("BL_VERSION", "468")
System.put_env("BL_GAME_HOST", "localhost")
System.put_env("BL_GAME_PORT", "43594")
# Postgres only — skip all of these for the default SQLite adapter:
System.put_env("BL_DATABASE", "bl-dev")
System.put_env("BL_DATABASE_USER", "bl")
System.put_env("BL_DATABASE_PASSWORD", "bl")
System.put_env("BL_DATABASE_HOST", "localhost")
System.put_env("BL_DATABASE_PORT", "5432")
- Pull deps and set up the database:
$ mix deps.get
$ mix ecto.create # no-op on SQLite — the file is created automatically under priv/repository/
$ mix ecto.migrate
- Boot the server:
$ mix run --no-halt # or `iex -S mix` for a shell
The game (and JS5 cache serving) listens on 43594. The operator admin panel — a small Phoenix LiveView for watching players and tick performance — runs on 4001, bound to 127.0.0.1.
Docker
There's a Dockerfile that compiles the app and runs it with mix run --no-halt (it runs from source, not an OTP release). Build it and run it directly, bind-mounting your cache into /app/cache.
RSA login encryption (optional)
The client can RSA-encrypt the login block. It's off by default and both sides have to agree:
- Generate a 1024-bit RSA keypair and write the private key PEM to
priv/rsa/private.pem(override the path withBL_RSA_KEY_PATH). - Turn it on:
export BL_RSA_ENABLED=true - Put the decimal modulus into the client's login config —
BL.Crypto.RSA.modulus_decimal/0prints it. - Restart both ends.
Core values
This is a labor of love, built for learning and game preservation — nothing more.
- No money, ever. No donations, no monetary contributions of any kind. If you want to support it, contribute your time and skill instead — that's worth far more.
- Not for profit — yours or anyone's. I don't endorse, condone, or permit this being used in any way that involves money changing hands: no paid memberships, no microtransactions, no selling items or services, no monetized hosting. If you run it, keep it free.
- Preservation over everything. The point is to understand and preserve what made these games special, in the open, for free.
These aren't just nice words — they're baked into the license.
License
Released under the PolyForm Noncommercial License 1.0.0: use, modify, and share it freely for any noncommercial purpose. Commercial use is not allowed. Patches you send in are accepted under the same terms.
Disclaimer
An independent, noncommercial project for education and game preservation. Not affiliated with, endorsed by, or sponsored by the original RuneScape rightsholders, and it ships no copyrighted game assets — you supply your own client and cache.