mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-11-14 11:03:53 +01:00
Wownerogue
A browser-based roguelike synchronized with crypto block timing. A run is a race against the next block: reach the exit before the block lands, or the house wins. The same codebase runs the solo dungeon, the social Tavern, and operator-selected PvP and race rulesets, with separate free and paid leaderboards. Self-hostable under the MIT License. See README.md to run it, docs/ARCHITECTURE.md for the design, and docs/DEPLOY.md to operate an instance.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* MatchEngine: server tick driver for a MatchRoom.
|
||||
*
|
||||
* The engine is intentionally thin: all state/rules live in MatchRoom, and this class owns
|
||||
* the timer that calls `room.resolveTick()` at a fixed interval. It also handles graceful
|
||||
* shutdown and can be used by MatchManager to drive many concurrent matches.
|
||||
*
|
||||
* Transport-agnostic: no Socket.IO here. The manager that owns this engine consumes the
|
||||
* tick result and broadcasts it.
|
||||
*/
|
||||
|
||||
class MatchEngine {
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {MatchRoom} opts.room
|
||||
* @param {number} [opts.tickMs] default 250ms
|
||||
* @param {Function} [opts.onTick] callback(tickResult, room)
|
||||
* @param {Function} [opts.onFinish] callback(room)
|
||||
*/
|
||||
constructor({ room, tickMs = 250, onTick = null, onFinish = null } = {}) {
|
||||
if (!room) throw new Error('MatchEngine requires a MatchRoom');
|
||||
this.room = room;
|
||||
this.tickMs = tickMs;
|
||||
this.onTick = onTick;
|
||||
this.onFinish = onFinish;
|
||||
this.timer = null;
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this.running) return false;
|
||||
const started = this.room.start();
|
||||
if (!started) return false;
|
||||
this.running = true;
|
||||
this.timer = setInterval(() => this._tick(), this.tickMs);
|
||||
return true;
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a single tick synchronously. Useful for tests and for manually stepping.
|
||||
* @returns {{tick:number, events:Array, finished:boolean}}
|
||||
*/
|
||||
tick() {
|
||||
return this._tick();
|
||||
}
|
||||
|
||||
_tick() {
|
||||
const result = this.room.resolveTick();
|
||||
if (this.onTick) this.onTick(result, this.room);
|
||||
if (result.finished) {
|
||||
this.stop();
|
||||
this.room.finalize();
|
||||
if (this.onFinish) this.onFinish(this.room);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force end (e.g. block deadline or hard ceiling). The manager should call this when
|
||||
* it knows the match must end regardless of in-engine state.
|
||||
* @param {string} reason
|
||||
*/
|
||||
expire(reason) {
|
||||
this.room.expire(reason);
|
||||
this.stop();
|
||||
this.room.finalize();
|
||||
if (this.onFinish) this.onFinish(this.room);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MatchEngine;
|
||||
Reference in New Issue
Block a user