Kopie van https://gitlab.com/studieverenigingvia/ict/centurion met een paar aanpassingen
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
4.9 KiB
210 lines
4.9 KiB
import {Socket} from "socket.io";
|
|
|
|
import User from "./User";
|
|
import {getIndex, getNextShot, getTimeline, getTimelineNames, indexForTime} from "./timeline";
|
|
import {getCurrentTime} from "./util";
|
|
|
|
export interface RoomOptions {
|
|
seekTime: number
|
|
timelineName: string
|
|
}
|
|
|
|
export default class Room {
|
|
id: number = 0;
|
|
users: User[] = [];
|
|
leader: User | null = null;
|
|
|
|
running = false;
|
|
startTime = 0;
|
|
currentSeconds = 0;
|
|
timelineIndex: number = 0;
|
|
|
|
seekTime: number = 0;
|
|
timelineName: string = 'Centurion';
|
|
|
|
// For debugging purposes
|
|
speedFactor = 1;
|
|
autoStart = false;
|
|
|
|
constructor(name: number) {
|
|
this.id = name;
|
|
}
|
|
|
|
serialize(user: User) {
|
|
return {
|
|
'id': this.id,
|
|
'userCount': this.users.length,
|
|
'isLeader': this.leader == user,
|
|
'running': this.running,
|
|
'startTime': this.startTime,
|
|
'timelineName': this.timelineName,
|
|
'seekTime': this.seekTime,
|
|
'readyToParticipate': user.readyToParticipate || this.leader == user,
|
|
'speedFactor': this.speedFactor
|
|
}
|
|
}
|
|
|
|
serializeTimeline(user: User) {
|
|
return getTimeline(this.timelineName);
|
|
}
|
|
|
|
sync() {
|
|
this.users.forEach(u => u.sync());
|
|
}
|
|
|
|
join(user: User) {
|
|
this.users.push(user);
|
|
user.setRoom(this);
|
|
|
|
if (!this.hasLeader()) {
|
|
this.setLeader(user);
|
|
}
|
|
|
|
if (this.autoStart) {
|
|
this.seekTime = 2500000;
|
|
this.running = true;
|
|
this.start();
|
|
}
|
|
|
|
this.sync();
|
|
}
|
|
|
|
leave(user: User) {
|
|
this.users.splice(this.users.indexOf(user), 1);
|
|
user.setRoom(null);
|
|
|
|
if (this.leader == user) {
|
|
this.setRandomLeader();
|
|
}
|
|
|
|
this.sync();
|
|
}
|
|
|
|
onBeforeDelete() {
|
|
}
|
|
|
|
setOptions(options: any) {
|
|
this.seekTime = Math.max(0, Math.min(options.seekTime, 250 * 60 * 1000))
|
|
if (getTimelineNames().indexOf(options.timelineName) >= 0) {
|
|
this.timelineName = options.timelineName;
|
|
}
|
|
this.sync()
|
|
}
|
|
|
|
start() {
|
|
this.running = true;
|
|
this.startTime = getCurrentTime() - this.seekTime
|
|
|
|
this.sync();
|
|
}
|
|
|
|
run(io: Socket) {
|
|
this.running = true;
|
|
this.startTime = Date.now();
|
|
|
|
// io.to(this.id.toString()).emit('timeline', {
|
|
// 'timeline': {
|
|
// }
|
|
// });
|
|
|
|
const doTick = () => {
|
|
if (this.users.length === 0) {
|
|
// this room is over.
|
|
return;
|
|
}
|
|
|
|
const timestamp = getIndex(this.timelineIndex);
|
|
const nextShot = getNextShot(this.timelineIndex);
|
|
|
|
if (!timestamp) {
|
|
// We are done.
|
|
io.to(this.id.toString()).emit('tick_event', {
|
|
tick: {
|
|
current: this.currentSeconds
|
|
}
|
|
});
|
|
console.log("Done");
|
|
this.running = false;
|
|
return;
|
|
}
|
|
|
|
console.log("ticking", this.currentSeconds);
|
|
|
|
io.to(this.id.toString()).emit('tick_event', {
|
|
tick: {
|
|
current: this.currentSeconds,
|
|
next: timestamp,
|
|
nextShot: nextShot
|
|
}
|
|
});
|
|
|
|
if (this.currentSeconds >= timestamp.timestamp) {
|
|
this.timelineIndex += 1;
|
|
}
|
|
|
|
this.currentSeconds += 1;
|
|
// We spend some time processing, wait a bit less than 1000ms
|
|
const nextTickTime = this.startTime + (1000 * this.currentSeconds / this.speedFactor);
|
|
const waitTime = nextTickTime - Date.now();
|
|
console.log("waiting", waitTime);
|
|
setTimeout(doTick, Math.floor(waitTime / this.speedFactor));
|
|
};
|
|
|
|
doTick();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param io
|
|
* @param {number} time
|
|
*/
|
|
seek(io: Socket, time: number) {
|
|
this.currentSeconds = time;
|
|
this.startTime = Date.now() - time * 1000;
|
|
this.timelineIndex = indexForTime(this.currentSeconds);
|
|
io.to(this.id.toString()).emit('seek', time);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
hasUsers() {
|
|
return this.users.length !== 0;
|
|
}
|
|
|
|
setRandomLeader() {
|
|
if (this.hasUsers()) {
|
|
this.leader = this.users[0];
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param id
|
|
* @returns {User|undefined}
|
|
*/
|
|
getUser(id: string) {
|
|
return this.users.find(u => u.id === id);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} id
|
|
*/
|
|
removeUser(id: string) {
|
|
this.users = this.users.filter(u => u.id !== id);
|
|
}
|
|
|
|
hasLeader(): boolean {
|
|
return this.leader != null;
|
|
}
|
|
|
|
setLeader(user: User) {
|
|
this.leader = user;
|
|
}
|
|
|
|
getLeader(): User | null {
|
|
return this.leader;
|
|
}
|
|
};
|
|
|