a RuneScape server emulator for the 468 client protocol written in Elixir/OTP
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Patrick W. b01234a8f8
All checks were successful
build / image (push) Successful in 27s
fix: Gmaul instant spec on switch (#225)
Reviewed-on: #225
2026-07-24 19:05:38 +00:00
.forgejo/workflows chore: update ci/cd 2026-07-01 17:05:56 -04:00
config chore: make logs stfu (#169) 2026-07-18 19:00:39 +00:00
dev feat: initial commit 2026-05-25 08:16:15 -04:00
lib fix: Gmaul instant spec on switch (#225) 2026-07-24 19:05:38 +00:00
priv feat: Bot Lending (#223) 2026-07-24 18:04:01 +00:00
scripts feat: CS2 debugging (#83) 2026-06-30 16:09:10 +00:00
test fix: Gmaul instant spec on switch (#225) 2026-07-24 19:05:38 +00:00
.dialyzer_ignore.exs chore: fix ci (#122) 2026-07-03 14:12:56 +00:00
.dockerignore chore: refactor dockerfile, docker-compose, dockerignore, etc 2026-06-28 10:09:20 -04:00
.formatter.exs feat: initial commit 2026-05-25 08:16:15 -04:00
docker-compose.yml feat: load test results dir (#145) 2026-07-06 23:40:22 +00:00
Dockerfile chore: refactor dockerfile, docker-compose, dockerignore, etc 2026-06-28 10:09:20 -04:00
LICENSE feat: documentation refactor, update readme, add license 2026-06-26 20:05:25 -04:00
mix.exs chore: fix ci 2026-06-29 20:02:11 -04:00
mix.lock feat: init 2026-05-31 09:25:50 -04:00
README.md chore: yoink 2026-07-06 13:34:19 -04:00

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/Server is the source of truth. Anything you find elsewhere is a mirror. The client lives next door at BlackLobster/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 matching Erlang/OTP27+ is fine)
  • bzip2 / libbz2 headers — the cache decompression NIF needs them
  • A database, either:
    • SQLite (the default) — single file, nothing extra to run
    • PostgreSQL 14+ — set BL_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

  1. Drop a config/.env.dev.exs file with whatever env you need. config/example.exs is 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")
  1. 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
  1. 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:

  1. Generate a 1024-bit RSA keypair and write the private key PEM to priv/rsa/private.pem (override the path with BL_RSA_KEY_PATH).
  2. Turn it on: export BL_RSA_ENABLED=true
  3. Put the decimal modulus into the client's login config — BL.Crypto.RSA.modulus_decimal/0 prints it.
  4. 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.