initial commit
This commit is contained in:
commit
e8c3f9862a
193 files changed
+29795
No files matched your search
@@ -0,0 +1,201 @@
|
||||
import { SocketClient } from './SocketClient.js';
|
||||
|
||||
const INPUT_RATE = 30;
|
||||
|
||||
export class NetworkClient {
|
||||
constructor(options = {}) {
|
||||
this.socket = new SocketClient(options);
|
||||
this.room = null;
|
||||
this.playerId = null;
|
||||
this.playerName = null;
|
||||
this.joined = false;
|
||||
this.creator = false;
|
||||
this.prev = null;
|
||||
this.prevAt = 0;
|
||||
this.curr = null;
|
||||
this.currAt = 0;
|
||||
this.onStateChange = null;
|
||||
this.onRoomError = null;
|
||||
this._input = null;
|
||||
this._inputTimer = null;
|
||||
|
||||
this.socket.onConnectionChange = (connected) => {
|
||||
if (connected && this.joined && this.room) {
|
||||
if (this.creator) {
|
||||
this._sendCreate();
|
||||
} else {
|
||||
this._sendJoin();
|
||||
}
|
||||
}
|
||||
this.onStateChange?.({ type: 'connection', connected });
|
||||
};
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.socket.connect();
|
||||
}
|
||||
|
||||
get connected() {
|
||||
return this.socket.connected;
|
||||
}
|
||||
|
||||
join(room, { id, name }) {
|
||||
this._enterRoom(room, { id, name }, false);
|
||||
}
|
||||
|
||||
create(room, { id, name }) {
|
||||
this._enterRoom(room, { id, name }, true);
|
||||
}
|
||||
|
||||
_enterRoom(room, { id, name }, isCreator) {
|
||||
const changingRoom = this.room && this.room !== room;
|
||||
if (changingRoom) {
|
||||
this.socket.unsubscribe(this._snapshotChannel());
|
||||
this.socket.unsubscribe(this._inputChannel());
|
||||
this._sendControl('leave');
|
||||
}
|
||||
this.room = room;
|
||||
this.playerId = id;
|
||||
this.playerName = name;
|
||||
this.joined = true;
|
||||
this.creator = isCreator;
|
||||
|
||||
this.prev = null;
|
||||
this.prevAt = 0;
|
||||
this.curr = null;
|
||||
this.currAt = 0;
|
||||
|
||||
this.socket.subscribe(this._snapshotChannel(), {
|
||||
onEvent: (event, payload) => {
|
||||
if (event === 'snapshot') {
|
||||
this._ingest(payload);
|
||||
} else if (event === 'room-error') {
|
||||
this.onRoomError?.(payload);
|
||||
}
|
||||
},
|
||||
});
|
||||
this.socket.subscribe(this._inputChannel());
|
||||
if (isCreator) {
|
||||
this._sendCreate();
|
||||
} else {
|
||||
this._sendJoin();
|
||||
}
|
||||
|
||||
if (!this._inputTimer) {
|
||||
this._inputTimer = setInterval(() => this._flushInput(), 1000 / INPUT_RATE);
|
||||
}
|
||||
}
|
||||
|
||||
leave() {
|
||||
if (!this.joined) return;
|
||||
this._sendControl('leave');
|
||||
this.joined = false;
|
||||
this.creator = false;
|
||||
this.room = null;
|
||||
this.prev = null;
|
||||
this.prevAt = 0;
|
||||
this.curr = null;
|
||||
this.currAt = 0;
|
||||
|
||||
if (this._inputTimer) {
|
||||
clearInterval(this._inputTimer);
|
||||
this._inputTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
abandonRoom() {
|
||||
if (this.room) {
|
||||
this.socket.unsubscribe(this._snapshotChannel());
|
||||
this.socket.unsubscribe(this._inputChannel());
|
||||
}
|
||||
this.joined = false;
|
||||
this.creator = false;
|
||||
this.room = null;
|
||||
this.prev = null;
|
||||
this.prevAt = 0;
|
||||
this.curr = null;
|
||||
this.currAt = 0;
|
||||
|
||||
if (this._inputTimer) {
|
||||
clearInterval(this._inputTimer);
|
||||
this._inputTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
this._sendControl('start');
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._sendControl('reset');
|
||||
}
|
||||
|
||||
sendInput(frame) {
|
||||
this._input = frame;
|
||||
}
|
||||
|
||||
stopSendingInput() {
|
||||
this._input = null;
|
||||
}
|
||||
|
||||
_flushInput() {
|
||||
if (!this._input || !this._connected()) return;
|
||||
const { id, keys, aim, fire, autoAim } = this._input;
|
||||
this.socket.trigger('client-input', this._inputChannel(), {
|
||||
id,
|
||||
keys,
|
||||
aim,
|
||||
fire,
|
||||
autoAim,
|
||||
});
|
||||
}
|
||||
|
||||
_connected() {
|
||||
return this.joined && this.room && this.socket.connected;
|
||||
}
|
||||
|
||||
_snapshotChannel() {
|
||||
return `game.${this.room}`;
|
||||
}
|
||||
|
||||
_inputChannel() {
|
||||
return `game.${this.room}.input`;
|
||||
}
|
||||
|
||||
_sendControl(type) {
|
||||
if (!this._connected()) return;
|
||||
this.socket.trigger(`client-${type}`, this._inputChannel(), {
|
||||
type,
|
||||
id: this.playerId,
|
||||
name: this.playerName,
|
||||
});
|
||||
}
|
||||
|
||||
_sendJoin() {
|
||||
if (!this.room || !this.playerId) return;
|
||||
this.socket.trigger('client-join', this._inputChannel(), {
|
||||
type: 'join',
|
||||
id: this.playerId,
|
||||
name: this.playerName,
|
||||
});
|
||||
}
|
||||
|
||||
_sendCreate() {
|
||||
if (!this.room || !this.playerId) return;
|
||||
this.socket.trigger('client-create', this._inputChannel(), {
|
||||
type: 'create',
|
||||
id: this.playerId,
|
||||
name: this.playerName,
|
||||
});
|
||||
}
|
||||
|
||||
_ingest(payload) {
|
||||
if (this.curr && payload.seq !== undefined && this.curr.seq !== undefined && payload.seq <= this.curr.seq) {
|
||||
return;
|
||||
}
|
||||
this.prev = this.curr;
|
||||
this.prevAt = this.currAt;
|
||||
this.curr = payload;
|
||||
this.currAt = performance.now();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user