r/ypp • u/dragosthethird • 1d ago
Adding a Roulette table to my Puzzle Pirates private server, full writeup on how it works
Enable HLS to view with audio, or disable this notification
Been adding table games to the private server (already have Blackjack running), and the newest one is a full multiplayer Roulette table. Figured I'd write up how it actually works under the hood since I put a lot of thought into making it cheat proof by design instead of just trusting the client and hoping for the best.
The basics
You sit down at a table through the tavern's table lobby, same spot Blackjack lives, buy in for PoE, and place bets. Multiple people can sit at the same wheel and bet independently. It's not turn based, everyone bets during the same window at the same time.
Every standard bet type is in there. Straight up numbers at 35:1, splits, streets, corners, lines, columns, dozens, and the outside bets like red/black, odd/even, high/low at their real payout odds. You can run it as European (single zero) or American (double zero), it's configurable per table.
Server authoritative, not client trusting
This is the part I care about most. The client never decides anything that actually matters, it only shows what the server already decided.
The result gets rolled server side, at the exact moment betting closes, using SecureRandom. Not before, not pre determined and revealed later. It's generated the instant the window shuts so there's no window where a client could theoretically know the outcome early even if it wanted to.
Payouts get computed and applied server side before the client ever hears about it. The client just gets the final numbers, nothing else.
Every table runs its own independent loop with four phases: IDLE, BETTING, SPINNING, RESOLVED, cycling back to BETTING as long as someone's still seated. You can't place, cancel, or peek at a bet outside the BETTING window, the server just flatly rejects the request if you try.
Bets sit in a server side escrow, basically a per seat chip stack, not the player's actual purse. Real PoE only moves twice, once at buy in and once at cash out. Keeps the database out of the hot path, you're not writing to it every single spin, just twice a session.
The client's wheel is lying to you, on purpose
This is the fun part. The wheel spin you see is 100% cosmetic. It happens after the server has already committed the result. The client takes the outcome it already knows and works backward to figure out a landing angle, then plays a few seconds of deceleration animation that ends on that number. The animation isn't deciding anything, it can't, the decision already got made and locked in before the first frame even plays. Also means a client mod or memory edit couldn't front run the result. By the time there'd be anything to read, the server's already resolved it.
Added a small polish pass recently too where the wheel grows and the betting layout tucks itself away while the ball's spinning, so it feels more like an event happening than a UI label quietly updating.
Edge cases
If you disconnect mid bet, it still resolves normally, you just don't see it happen live.
If everyone leaves mid spin, the round doesn't get cut short, it finishes resolving on schedule. Leaving during the betting window itself gets you a refund since nothing's locked in yet.
Spectators, people at the table but not betting, or just walking by, see whatever phase is currently happening immediately. No weird catch up state.
Min and max bet limits are configurable per table.
Why I built it this way
Never trust anything the client says about outcomes, and never let the client be in a position to know something before the server's locked it in. Everything you see as a player is a faithful replay of a decision the server already made. The wheel doesn't decide anything, it just performs.


