A private server emulator for Endless Online, written in Java.
I originally wrote this whole thing in TypeScript. It worked, but everyone kept telling me to rewrite it in Java — better performance, actual type safety, easier to maintain long-term. So I did. The old TS version is still on the typescript branch if you're curious.
It runs an EO server. Most of the gameplay works:
- Account creation, login, character management
- Walking around, warping between maps, doors, spawn points (~290 maps)
- NPCs that wander, chase, fight, and drop loot
- Melee combat with proper damage formulas, XP, and leveling
- Items — pick up, drop, equip, use, trade, all of it
- Chat — local, global, party, guild, admin, whispers
- Shops, banks, lockers, barbers, chests, jukeboxes
- Guilds with ranks, recruitment, guild bank
- Town boards
- Sit on the ground or in chairs, emotes, face direction
- Admin commands — $kick, $ban, $warp, $item, $setlevel, you name it
- Marriage ceremonies (mostly)
- Quest and spell handlers are stubbed out, ready to be filled in
Not everything is production-ready but the core loop works from login to gameplay.
Need Java 21. Then just:
./gradlew run --no-daemonPut your pub files in data/pub/ and maps in data/maps/. Binds to 0.0.0.0:8082 by default, tweak in config/config.json.
src/main/java/com/eocobra/
├── Main.java boots the server
├── commands/ admin commands
├── db/ SQLite stuff
├── game/ configs, formulas, maps, NPC AI
├── handlers/ 40 packet handlers
├── net/ server + client networking
└── utils/ logger, password hashing
config/ 6 JSON config files
data/ pub files, maps, database
dashboard/ Electron management dashboard
Simplified the config from 18 files down to 6:
config.json— host, port, version, db pathbalance.json— rates, limits, formulasnpcs.json— NPC AI, drops, shops, skills, speechrules.json— admin perms, PK settings, arenasworld.json— guilds, boards, spawns, jail, misclang.json— all the in-game text
Because everyone told me to.
But also — Java NIO handles connections better than Node for this kind of thing, eolib-java gives proper type-safe packet handling, Argon2id is a real password hash instead of SHA-256, and Gradle just makes the build simpler. No more node_modules eating disk space.
MIT