mirror of
https://git.rezel.net/LudoTech/traque.git
synced 2026-02-09 10:20:16 +01:00
Refactored code to remove useless classes, fix #17
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
import { io, game, penaltyController } from "./index.js";
|
import { io } from "./index.js";
|
||||||
|
import game from "./game.js"
|
||||||
|
import zone from "./zone_manager.js"
|
||||||
|
import penaltyController from "./penalty_controller.js";
|
||||||
import { playersBroadcast, sendUpdatedTeamInformations } from "./team_socket.js";
|
import { playersBroadcast, sendUpdatedTeamInformations } from "./team_socket.js";
|
||||||
|
|
||||||
import { config } from "dotenv";
|
import { config } from "dotenv";
|
||||||
@@ -47,11 +50,11 @@ export function initAdminSocketHandler() {
|
|||||||
//Other settings that need initialization
|
//Other settings that need initialization
|
||||||
socket.emit("penalty_settings", penaltyController.settings)
|
socket.emit("penalty_settings", penaltyController.settings)
|
||||||
socket.emit("game_settings", game.settings)
|
socket.emit("game_settings", game.settings)
|
||||||
socket.emit("zone_settings", game.zone.zoneSettings)
|
socket.emit("zone_settings", zone.zoneSettings)
|
||||||
socket.emit("zone", game.zone.currentZone)
|
socket.emit("zone", zone.currentZone)
|
||||||
socket.emit("new_zone", {
|
socket.emit("new_zone", {
|
||||||
begin: game.zone.currentStartZone,
|
begin: zone.currentStartZone,
|
||||||
end: game.zone.nextZone
|
end: zone.nextZone
|
||||||
})
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -79,9 +82,9 @@ export function initAdminSocketHandler() {
|
|||||||
}
|
}
|
||||||
if (!game.setZoneSettings(settings)) {
|
if (!game.setZoneSettings(settings)) {
|
||||||
socket.emit("error", "Error changing zone");
|
socket.emit("error", "Error changing zone");
|
||||||
socket.emit("zone_settings", game.zone.zoneSettings) //Still broadcast the old config to the client who submited an incorrect config to keep the client up to date
|
socket.emit("zone_settings", zone.zoneSettings) //Still broadcast the old config to the client who submited an incorrect config to keep the client up to date
|
||||||
} else {
|
} else {
|
||||||
secureAdminBroadcast("zone_settings", game.zone.zoneSettings)
|
secureAdminBroadcast("zone_settings", zone.zoneSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { secureAdminBroadcast } from "./admin_socket.js";
|
import { secureAdminBroadcast } from "./admin_socket.js";
|
||||||
import { penaltyController } from "./index.js";
|
|
||||||
import { isInCircle } from "./map_utils.js";
|
import { isInCircle } from "./map_utils.js";
|
||||||
import { playersBroadcast, sendUpdatedTeamInformations } from "./team_socket.js";
|
import { playersBroadcast, sendUpdatedTeamInformations } from "./team_socket.js";
|
||||||
import { ZoneManager } from "./zone_manager.js";
|
|
||||||
|
import penaltyController from "./penalty_controller.js";
|
||||||
|
import zoneManager from "./zone_manager.js";
|
||||||
|
|
||||||
export const GameState = {
|
export const GameState = {
|
||||||
SETUP: "setup",
|
SETUP: "setup",
|
||||||
@@ -11,23 +12,20 @@ export const GameState = {
|
|||||||
FINISHED: "finished"
|
FINISHED: "finished"
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Game {
|
export default {
|
||||||
constructor(onUpdateZone, onUpdateNewZone) {
|
teams : [],
|
||||||
this.teams = [];
|
state : GameState.SETUP,
|
||||||
this.state = GameState.SETUP;
|
settings : {
|
||||||
this.zone = new ZoneManager(onUpdateZone, onUpdateNewZone)
|
loserEndGameMessage: "",
|
||||||
this.settings = {
|
winnerEndGameMessage: "",
|
||||||
loserEndGameMessage: "",
|
capturedMessage: "",
|
||||||
winnerEndGameMessage: "",
|
waitingMessage: "Jeu en préparation, veuillez patienter."
|
||||||
capturedMessage: "",
|
},
|
||||||
waitingMessage: "Jeu en préparation, veuillez patienter."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changeSettings(newSettings) {
|
changeSettings(newSettings) {
|
||||||
this.settings = {...this.settings, ...newSettings};
|
this.settings = {...this.settings, ...newSettings};
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
setState(newState) {
|
setState(newState) {
|
||||||
if (Object.values(GameState).indexOf(newState) == -1) {
|
if (Object.values(GameState).indexOf(newState) == -1) {
|
||||||
@@ -36,19 +34,19 @@ export default class Game {
|
|||||||
//The game has started
|
//The game has started
|
||||||
if (newState == GameState.PLAYING) {
|
if (newState == GameState.PLAYING) {
|
||||||
penaltyController.start();
|
penaltyController.start();
|
||||||
if (!this.zone.ready()) {
|
if (!zoneManager.ready()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.initLastSentLocations();
|
this.initLastSentLocations();
|
||||||
this.zone.reset()
|
zoneManager.reset()
|
||||||
//If the zone cannot be setup, reset everything
|
//If the zone cannot be setup, reset everything
|
||||||
if (!this.zone.start()) {
|
if (!zoneManager.start()) {
|
||||||
this.setState(GameState.SETUP);
|
this.setState(GameState.SETUP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newState != GameState.PLAYING) {
|
if (newState != GameState.PLAYING) {
|
||||||
this.zone.reset();
|
zoneManager.reset();
|
||||||
penaltyController.stop();
|
penaltyController.stop();
|
||||||
}
|
}
|
||||||
//Game reset
|
//Game reset
|
||||||
@@ -65,7 +63,7 @@ export default class Game {
|
|||||||
}
|
}
|
||||||
this.state = newState;
|
this.state = newState;
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
getNewTeamId() {
|
getNewTeamId() {
|
||||||
let id = null;
|
let id = null;
|
||||||
@@ -73,11 +71,11 @@ export default class Game {
|
|||||||
id = Math.floor(Math.random() * 1_000_000);
|
id = Math.floor(Math.random() * 1_000_000);
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
},
|
||||||
|
|
||||||
createCaptureCode() {
|
createCaptureCode() {
|
||||||
return Math.floor(Math.random() * 10000)
|
return Math.floor(Math.random() * 10000)
|
||||||
}
|
},
|
||||||
|
|
||||||
addTeam(teamName) {
|
addTeam(teamName) {
|
||||||
let id = this.getNewTeamId();
|
let id = this.getNewTeamId();
|
||||||
@@ -100,7 +98,7 @@ export default class Game {
|
|||||||
});
|
});
|
||||||
this.updateTeamChasing();
|
this.updateTeamChasing();
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
playingTeamCount() {
|
playingTeamCount() {
|
||||||
let res = 0;
|
let res = 0;
|
||||||
@@ -110,7 +108,7 @@ export default class Game {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
return res;
|
return res;
|
||||||
}
|
},
|
||||||
|
|
||||||
updateTeamChasing() {
|
updateTeamChasing() {
|
||||||
if (this.playingTeamCount() <= 2) {
|
if (this.playingTeamCount() <= 2) {
|
||||||
@@ -138,16 +136,16 @@ export default class Game {
|
|||||||
this.getTeam(previousTeam).enemyName = this.getTeam(firstTeam).name;
|
this.getTeam(previousTeam).enemyName = this.getTeam(firstTeam).name;
|
||||||
secureAdminBroadcast("teams", this.teams)
|
secureAdminBroadcast("teams", this.teams)
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
reorderTeams(newOrder) {
|
reorderTeams(newOrder) {
|
||||||
this.teams = newOrder;
|
this.teams = newOrder;
|
||||||
return this.updateTeamChasing();
|
return this.updateTeamChasing();
|
||||||
}
|
},
|
||||||
|
|
||||||
getTeam(teamId) {
|
getTeam(teamId) {
|
||||||
return this.teams.find(t => t.id === teamId);
|
return this.teams.find(t => t.id === teamId);
|
||||||
}
|
},
|
||||||
|
|
||||||
updateTeam(teamId, newTeam) {
|
updateTeam(teamId, newTeam) {
|
||||||
this.teams = this.teams.map((t) => {
|
this.teams = this.teams.map((t) => {
|
||||||
@@ -160,7 +158,7 @@ export default class Game {
|
|||||||
this.updateTeamChasing();
|
this.updateTeamChasing();
|
||||||
penaltyController.checkPenalties();
|
penaltyController.checkPenalties();
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
updateLocation(teamId, location) {
|
updateLocation(teamId, location) {
|
||||||
let team = this.getTeam(teamId);
|
let team = this.getTeam(teamId);
|
||||||
@@ -176,7 +174,7 @@ export default class Game {
|
|||||||
team.ready = isInCircle({ lat: location[0], lng: location[1] }, team.startingArea.center, team.startingArea.radius)
|
team.ready = isInCircle({ lat: location[0], lng: location[1] }, team.startingArea.center, team.startingArea.radius)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
//Make it so that when a team requests the location of a team that has never sent their locaiton
|
//Make it so that when a team requests the location of a team that has never sent their locaiton
|
||||||
//Their position at the begining of the game is sent
|
//Their position at the begining of the game is sent
|
||||||
@@ -186,7 +184,7 @@ export default class Game {
|
|||||||
team.locationSendDeadline = Number(new Date()) + penaltyController.settings.allowedTimeBetweenPositionUpdate * 60 * 1000;
|
team.locationSendDeadline = Number(new Date()) + penaltyController.settings.allowedTimeBetweenPositionUpdate * 60 * 1000;
|
||||||
sendUpdatedTeamInformations(team.id);
|
sendUpdatedTeamInformations(team.id);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
sendLocation(teamId) {
|
sendLocation(teamId) {
|
||||||
let team = this.getTeam(teamId);
|
let team = this.getTeam(teamId);
|
||||||
@@ -203,7 +201,7 @@ export default class Game {
|
|||||||
team.enemyLocation = this.getTeam(team.chasing).lastSentLocation;
|
team.enemyLocation = this.getTeam(team.chasing).lastSentLocation;
|
||||||
}
|
}
|
||||||
return team;
|
return team;
|
||||||
}
|
},
|
||||||
|
|
||||||
removeTeam(teamId) {
|
removeTeam(teamId) {
|
||||||
if (this.getTeam(teamId) == undefined) {
|
if (this.getTeam(teamId) == undefined) {
|
||||||
@@ -213,7 +211,7 @@ export default class Game {
|
|||||||
this.teams = this.teams.filter(t => t.id !== teamId);
|
this.teams = this.teams.filter(t => t.id !== teamId);
|
||||||
this.updateTeamChasing();
|
this.updateTeamChasing();
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request a capture initiated by the team with id teamId (the one trying to capture)
|
* Request a capture initiated by the team with id teamId (the one trying to capture)
|
||||||
@@ -231,7 +229,7 @@ export default class Game {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a team to captured and update the chase chain
|
* Set a team to captured and update the chase chain
|
||||||
@@ -240,7 +238,7 @@ export default class Game {
|
|||||||
capture(teamId) {
|
capture(teamId) {
|
||||||
this.getTeam(teamId).captured = true
|
this.getTeam(teamId).captured = true
|
||||||
this.updateTeamChasing();
|
this.updateTeamChasing();
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the settings of the Zone manager
|
* Change the settings of the Zone manager
|
||||||
@@ -253,12 +251,12 @@ export default class Game {
|
|||||||
if (this.state == GameState.PLAYING || this.state == GameState.FINISHED) {
|
if (this.state == GameState.PLAYING || this.state == GameState.FINISHED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.zone.udpateSettings(newSettings)
|
return zoneManager.udpateSettings(newSettings)
|
||||||
}
|
},
|
||||||
|
|
||||||
finishGame() {
|
finishGame() {
|
||||||
this.setState(GameState.FINISHED);
|
this.setState(GameState.FINISHED);
|
||||||
this.zone.reset();
|
zoneManager.reset();
|
||||||
playersBroadcast("game_state", this.state);
|
playersBroadcast("game_state", this.state);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,10 @@ import { createServer } from "https";
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
|
|
||||||
import { Server } from "socket.io";
|
import { Server } from "socket.io";
|
||||||
import Game from "./game.js";
|
|
||||||
import { config } from "dotenv";
|
import { config } from "dotenv";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { initAdminSocketHandler, secureAdminBroadcast } from "./admin_socket.js";
|
import { initAdminSocketHandler } from "./admin_socket.js";
|
||||||
import { initTeamSocket, playersBroadcast } from "./team_socket.js";
|
import { initTeamSocket } from "./team_socket.js";
|
||||||
import { PenaltyController } from "./penalty_controller.js";
|
|
||||||
import { initPhotoUpload } from "./photo.js";
|
import { initPhotoUpload } from "./photo.js";
|
||||||
//extract admin password from .env file
|
//extract admin password from .env file
|
||||||
config();
|
config();
|
||||||
@@ -35,22 +33,6 @@ export const io = new Server(httpsServer, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//Zone update broadcast function, called by the game object
|
|
||||||
function onUpdateNewZone(newZone) {
|
|
||||||
playersBroadcast("new_zone", newZone)
|
|
||||||
secureAdminBroadcast("new_zone", newZone)
|
|
||||||
}
|
|
||||||
|
|
||||||
function onUpdateZone(zone) {
|
|
||||||
playersBroadcast("zone", zone)
|
|
||||||
secureAdminBroadcast("zone", zone)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const game = new Game(onUpdateZone, onUpdateNewZone);
|
|
||||||
export const penaltyController = new PenaltyController();
|
|
||||||
|
|
||||||
|
|
||||||
initAdminSocketHandler();
|
initAdminSocketHandler();
|
||||||
initTeamSocket();
|
initTeamSocket();
|
||||||
initPhotoUpload();
|
initPhotoUpload();
|
||||||
@@ -1,21 +1,18 @@
|
|||||||
import { getDistanceFromLatLon, isInCircle } from "./map_utils.js";
|
import { isInCircle } from "./map_utils.js";
|
||||||
import { sendUpdatedTeamInformations, teamBroadcast } from "./team_socket.js";
|
import { sendUpdatedTeamInformations, teamBroadcast } from "./team_socket.js";
|
||||||
import { GameState } from "./game.js";
|
|
||||||
import { secureAdminBroadcast } from "./admin_socket.js";
|
import { secureAdminBroadcast } from "./admin_socket.js";
|
||||||
import { game } from "./index.js";
|
import game, {GameState} from "./game.js";
|
||||||
|
import zone from "./zone_manager.js";
|
||||||
|
|
||||||
export class PenaltyController {
|
export default {
|
||||||
constructor() {
|
outOfBoundsSince: {},
|
||||||
|
checkIntervalId: null,
|
||||||
|
settings: {
|
||||||
|
allowedTimeOutOfZone: 10,
|
||||||
|
allowedTimeBetweenPositionUpdate: 10,
|
||||||
//Number of penalties needed to be eliminated
|
//Number of penalties needed to be eliminated
|
||||||
this.game = game;
|
maxPenalties: 3
|
||||||
this.outOfBoundsSince = {};
|
},
|
||||||
this.checkIntervalId = null;
|
|
||||||
this.settings = {
|
|
||||||
allowedTimeOutOfZone: 10,
|
|
||||||
allowedTimeBetweenPositionUpdate: 10,
|
|
||||||
maxPenalties: 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.outOfBoundsSince = {};
|
this.outOfBoundsSince = {};
|
||||||
@@ -24,12 +21,12 @@ export class PenaltyController {
|
|||||||
}
|
}
|
||||||
//Watch periodically if all teams need are following the rules
|
//Watch periodically if all teams need are following the rules
|
||||||
this.checkIntervalId = setInterval(() => {
|
this.checkIntervalId = setInterval(() => {
|
||||||
if (this.game.state == GameState.PLAYING) {
|
if (game.state == GameState.PLAYING) {
|
||||||
this.watchPositionUpdate();
|
this.watchPositionUpdate();
|
||||||
this.watchZone();
|
this.watchZone();
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
},
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
this.outOfBoundsSince = {};
|
this.outOfBoundsSince = {};
|
||||||
@@ -37,7 +34,7 @@ export class PenaltyController {
|
|||||||
clearInterval(this.checkIntervalId)
|
clearInterval(this.checkIntervalId)
|
||||||
this.checkIntervalId = null;
|
this.checkIntervalId = null;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
updateSettings(newSettings) {
|
updateSettings(newSettings) {
|
||||||
//Sanitize input
|
//Sanitize input
|
||||||
@@ -47,14 +44,14 @@ export class PenaltyController {
|
|||||||
|
|
||||||
this.settings = { ...this.settings, ...newSettings };
|
this.settings = { ...this.settings, ...newSettings };
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increment the penalty score of a team, send a message to the team and eliminated if necessary
|
* Increment the penalty score of a team, send a message to the team and eliminated if necessary
|
||||||
* @param {Number} teamId The team that will recieve a penalty
|
* @param {Number} teamId The team that will recieve a penalty
|
||||||
*/
|
*/
|
||||||
addPenalty(teamId) {
|
addPenalty(teamId) {
|
||||||
let team = this.game.getTeam(teamId);
|
let team = game.getTeam(teamId);
|
||||||
if (!team) {
|
if (!team) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -63,7 +60,7 @@ export class PenaltyController {
|
|||||||
}
|
}
|
||||||
team.penalties++;
|
team.penalties++;
|
||||||
if (team.penalties >= this.settings.maxPenalties) {
|
if (team.penalties >= this.settings.maxPenalties) {
|
||||||
this.game.capture(team.id);
|
game.capture(team.id);
|
||||||
sendUpdatedTeamInformations(teamId);
|
sendUpdatedTeamInformations(teamId);
|
||||||
sendUpdatedTeamInformations(team.chased);
|
sendUpdatedTeamInformations(team.chased);
|
||||||
teamBroadcast(teamId, "warning", "You have been eliminated (reason: too many penalties)")
|
teamBroadcast(teamId, "warning", "You have been eliminated (reason: too many penalties)")
|
||||||
@@ -72,29 +69,29 @@ export class PenaltyController {
|
|||||||
teamBroadcast(teamId, "warning", `You recieved a penalty (${team.penalties}/${this.settings.maxPenalties})`)
|
teamBroadcast(teamId, "warning", `You recieved a penalty (${team.penalties}/${this.settings.maxPenalties})`)
|
||||||
sendUpdatedTeamInformations(teamId);
|
sendUpdatedTeamInformations(teamId);
|
||||||
}
|
}
|
||||||
secureAdminBroadcast("teams", this.game.teams)
|
secureAdminBroadcast("teams", game.teams)
|
||||||
}
|
},
|
||||||
|
|
||||||
checkPenalties() {
|
checkPenalties() {
|
||||||
for (let team of game.teams) {
|
for (let team of game.teams) {
|
||||||
if (team.penalties >= this.settings.maxPenalties) {
|
if (team.penalties >= this.settings.maxPenalties) {
|
||||||
this.game.capture(team.id);
|
game.capture(team.id);
|
||||||
sendUpdatedTeamInformations(team.id);
|
sendUpdatedTeamInformations(team.id);
|
||||||
sendUpdatedTeamInformations(team.chased);
|
sendUpdatedTeamInformations(team.chased);
|
||||||
teamBroadcast(team.id, "warning", "You have been eliminated (reason: too many penalties)")
|
teamBroadcast(team.id, "warning", "You have been eliminated (reason: too many penalties)")
|
||||||
teamBroadcast(team.chased, "success", "The team you were chasing has been eliminated")
|
teamBroadcast(team.chased, "success", "The team you were chasing has been eliminated")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
watchZone() {
|
watchZone() {
|
||||||
this.game.teams.forEach((team) => {
|
game.teams.forEach((team) => {
|
||||||
if (team.captured) { return }
|
if (team.captured) { return }
|
||||||
//All the informations are not ready yet
|
//All the informations are not ready yet
|
||||||
if (team.currentLocation == null || this.game.zone.currentZone == null) {
|
if (team.currentLocation == null || zone.currentZone == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isInCircle({ lat: team.currentLocation[0], lng: team.currentLocation[1] }, this.game.zone.currentZone.center, this.game.zone.currentZone.radius)) {
|
if (!isInCircle({ lat: team.currentLocation[0], lng: team.currentLocation[1] }, zone.currentZone.center, zone.currentZone.radius)) {
|
||||||
//The team was not previously out of the zone
|
//The team was not previously out of the zone
|
||||||
if (!this.outOfBoundsSince[team.id]) {
|
if (!this.outOfBoundsSince[team.id]) {
|
||||||
this.outOfBoundsSince[team.id] = new Date();
|
this.outOfBoundsSince[team.id] = new Date();
|
||||||
@@ -111,11 +108,11 @@ export class PenaltyController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
|
||||||
|
|
||||||
watchPositionUpdate() {
|
watchPositionUpdate() {
|
||||||
this.game.teams.forEach((team) => {
|
game.teams.forEach((team) => {
|
||||||
//If the team has not sent their location for more than the allowed period, automatically send it and add a penalty
|
//If the team has not sent their location for more than the allowed period, automatically send it and add a penalty
|
||||||
if (team.captured) { return }
|
if (team.captured) { return }
|
||||||
if (team.locationSendDeadline == null) {
|
if (team.locationSendDeadline == null) {
|
||||||
@@ -124,12 +121,12 @@ export class PenaltyController {
|
|||||||
}
|
}
|
||||||
if (new Date() > team.locationSendDeadline) {
|
if (new Date() > team.locationSendDeadline) {
|
||||||
this.addPenalty(team.id);
|
this.addPenalty(team.id);
|
||||||
this.game.sendLocation(team.id);
|
game.sendLocation(team.id);
|
||||||
sendUpdatedTeamInformations(team.id);
|
sendUpdatedTeamInformations(team.id);
|
||||||
secureAdminBroadcast("teams", this.game.teams)
|
secureAdminBroadcast("teams", game.teams)
|
||||||
}else if(Math.abs(new Date() - team.locationSendDeadline - 60 * 1000) < 100) {
|
} else if (Math.abs(new Date() - team.locationSendDeadline - 60 * 1000) < 100) {
|
||||||
teamBroadcast(team.id, "warning", `You have one minute left to udpate your location.`)
|
teamBroadcast(team.id, "warning", `You have one minute left to udpate your location.`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { app, game } from "./index.js";
|
import { app } from "./index.js";
|
||||||
import multer from "multer";
|
import multer from "multer";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import game from "./game.js";
|
||||||
const UPLOAD_DIR = "uploads/"
|
const UPLOAD_DIR = "uploads/"
|
||||||
const ALLOWED_MIME = [
|
const ALLOWED_MIME = [
|
||||||
"image/png",
|
"image/png",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { secureAdminBroadcast } from "./admin_socket.js";
|
import { secureAdminBroadcast } from "./admin_socket.js";
|
||||||
import { io, game } from "./index.js";
|
import { io} from "./index.js";
|
||||||
|
import game from "./game.js";
|
||||||
|
import zone from "./zone_manager.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a socket message to all the players of a team
|
* Send a socket message to all the players of a team
|
||||||
@@ -79,10 +81,10 @@ export function initTeamSocket() {
|
|||||||
socket.emit("login_response", true);
|
socket.emit("login_response", true);
|
||||||
socket.emit("game_state", game.state)
|
socket.emit("game_state", game.state)
|
||||||
socket.emit("game_settings", game.settings)
|
socket.emit("game_settings", game.settings)
|
||||||
socket.emit("zone", game.zone.currentZone)
|
socket.emit("zone", zone.currentZone)
|
||||||
socket.emit("new_zone", {
|
socket.emit("new_zone", {
|
||||||
begin: game.zone.currentStartZone,
|
begin: zone.currentStartZone,
|
||||||
end: game.zone.nextZone
|
end: zone.nextZone
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,40 @@
|
|||||||
import { randomCirclePoint } from 'random-location'
|
import { randomCirclePoint } from 'random-location'
|
||||||
import { isInCircle } from './map_utils.js';
|
import { isInCircle } from './map_utils.js';
|
||||||
import { map } from './util.js';
|
import { map } from './util.js';
|
||||||
|
import { playersBroadcast } from './team_socket.js';
|
||||||
|
import { secureAdminBroadcast } from './admin_socket.js';
|
||||||
|
|
||||||
export class ZoneManager {
|
export default {
|
||||||
constructor(onZoneUpdate, onNextZoneUpdate) {
|
//Setings storing where the zone will start, end and how it should evolve
|
||||||
//Setings storing where the zone will start, end and how it should evolve
|
//The zone will start by staying at its mzx value for reductionInterval minutes
|
||||||
//The zone will start by staying at its mzx value for reductionInterval minutes
|
//and then reduce during reductionDuration minutes, then wait again...
|
||||||
//and then reduce during reductionDuration minutes, then wait again...
|
//The reduction factor is such that after reductionCount the zone will be the min zone
|
||||||
//The reduction factor is such that after reductionCount the zone will be the min zone
|
//a call to onZoneUpdate will be made every updateIntervalSeconds when the zone is changing
|
||||||
//a call to onZoneUpdate will be made every updateIntervalSeconds when the zone is changing
|
//a call to onNextZoneUpdate will be made when the zone reduction ends and a new next zone is announced
|
||||||
//a call to onNextZoneUpdate will be made when the zone reduction ends and a new next zone is announced
|
zoneSettings: {
|
||||||
this.zoneSettings = {
|
min: { center: null, radius: null },
|
||||||
min: { center: null, radius: null },
|
max: { center: null, radius: null },
|
||||||
max: { center: null, radius: null },
|
reductionCount: 2,
|
||||||
reductionCount: 2,
|
reductionDuration: 1,
|
||||||
reductionDuration: 1,
|
reductionInterval: 1,
|
||||||
reductionInterval: 1,
|
updateIntervalSeconds: 1,
|
||||||
updateIntervalSeconds: 1,
|
},
|
||||||
}
|
|
||||||
this.nextZoneDecrement = null;
|
|
||||||
//Live location of the zone
|
|
||||||
this.currentZone = { center: null, radius: null };
|
|
||||||
|
|
||||||
//If the zone is shrinking, this is the target of the current shrinking
|
nextZoneDecrement: null,
|
||||||
//If the zone is not shrinking, this will be the target of the next shrinking
|
//Live location of the zone
|
||||||
this.nextZone = { center: null, radius: null };
|
currentZone: { center: null, radius: null },
|
||||||
|
|
||||||
//Zone at the begining of the shrinking
|
//If the zone is shrinking, this is the target of the current shrinking
|
||||||
this.currentStartZone = { center: null, radius: null };
|
//If the zone is not shrinking, this will be the target of the next shrinking
|
||||||
|
nextZone: { center: null, radius: null },
|
||||||
|
|
||||||
this.startDate = null;
|
//Zone at the begining of the shrinking
|
||||||
this.started = false;
|
currentStartZone: { center: null, radius: null },
|
||||||
this.updateIntervalId = null;
|
|
||||||
this.nextZoneTimeoutId = null;
|
|
||||||
|
|
||||||
this.onZoneUpdate = onZoneUpdate;
|
startDate: null,
|
||||||
this.onNextZoneUpdate = onNextZoneUpdate
|
started: false,
|
||||||
}
|
updateIntervalId: null,
|
||||||
|
nextZoneTimeoutId: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if a given configuration object is valid, i.e if all needed values are well defined
|
* Test if a given configuration object is valid, i.e if all needed values are well defined
|
||||||
@@ -51,14 +49,14 @@ export class ZoneManager {
|
|||||||
if (settings.max && (typeof settings.max.radius != "number" || typeof settings.max.center.lat != "number" || typeof settings.max.center.lng != "number")) { return false }
|
if (settings.max && (typeof settings.max.radius != "number" || typeof settings.max.center.lat != "number" || typeof settings.max.center.lng != "number")) { return false }
|
||||||
if (settings.min && (typeof settings.min.radius != "number" || typeof settings.min.center.lat != "number" || typeof settings.min.center.lng != "number")) { return false }
|
if (settings.min && (typeof settings.min.radius != "number" || typeof settings.min.center.lat != "number" || typeof settings.min.center.lng != "number")) { return false }
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
/**
|
/**
|
||||||
* Test if the zone manager is ready to start
|
* Test if the zone manager is ready to start
|
||||||
* @returns true if the zone manager is ready to be started, false otherwise
|
* @returns true if the zone manager is ready to be started, false otherwise
|
||||||
*/
|
*/
|
||||||
ready() {
|
ready() {
|
||||||
return this.validateSettings(this.zoneSettings);
|
return this.validateSettings(this.zoneSettings);
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the settings of the zone, this can be done by passing an object containing the settings to change.
|
* Update the settings of the zone, this can be done by passing an object containing the settings to change.
|
||||||
@@ -80,7 +78,7 @@ export class ZoneManager {
|
|||||||
this.zoneSettings = { ...this.zoneSettings, ...newSettings };
|
this.zoneSettings = { ...this.zoneSettings, ...newSettings };
|
||||||
this.nextZoneDecrement = (this.zoneSettings.max.radius - this.zoneSettings.min.radius) / this.zoneSettings.reductionCount;
|
this.nextZoneDecrement = (this.zoneSettings.max.radius - this.zoneSettings.min.radius) / this.zoneSettings.reductionCount;
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reinitialize the object and stop all the tasks
|
* Reinitialize the object and stop all the tasks
|
||||||
@@ -96,7 +94,7 @@ export class ZoneManager {
|
|||||||
clearTimeout(this.nextZoneTimeoutId);
|
clearTimeout(this.nextZoneTimeoutId);
|
||||||
this.nextZoneTimeoutId = null;
|
this.nextZoneTimeoutId = null;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the zone reduction sequence
|
* Start the zone reduction sequence
|
||||||
@@ -110,7 +108,7 @@ export class ZoneManager {
|
|||||||
this.currentZone = JSON.parse(JSON.stringify(this.zoneSettings.max));
|
this.currentZone = JSON.parse(JSON.stringify(this.zoneSettings.max));
|
||||||
return this.setNextZone();
|
return this.setNextZone();
|
||||||
|
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the center of the next zone, this center need to satisfy two properties
|
* Get the center of the next zone, this center need to satisfy two properties
|
||||||
@@ -129,14 +127,14 @@ export class ZoneManager {
|
|||||||
res = randomCirclePoint({ latitude: this.currentZone.center.lat, longitude: this.currentZone.center.lng }, this.currentZone.radius - newRadius);
|
res = randomCirclePoint({ latitude: this.currentZone.center.lat, longitude: this.currentZone.center.lng }, this.currentZone.radius - newRadius);
|
||||||
ok = (isInCircle({ lat: res.latitude, lng: res.longitude }, this.zoneSettings.min.center, newRadius - this.zoneSettings.min.radius))
|
ok = (isInCircle({ lat: res.latitude, lng: res.longitude }, this.zoneSettings.min.center, newRadius - this.zoneSettings.min.radius))
|
||||||
}
|
}
|
||||||
if(tries>=MAX_TRIES) {
|
if (tries >= MAX_TRIES) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
lat: res.latitude,
|
lat: res.latitude,
|
||||||
lng: res.longitude
|
lng: res.longitude
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the next zone satifying the given settings, update the nextZone and currentStartZone
|
* Compute the next zone satifying the given settings, update the nextZone and currentStartZone
|
||||||
@@ -156,7 +154,7 @@ export class ZoneManager {
|
|||||||
} else if (this.currentZoneCount < this.zoneSettings.reductionCount) {
|
} else if (this.currentZoneCount < this.zoneSettings.reductionCount) {
|
||||||
this.nextZone.center = this.getRandomNextCenter(this.nextZone.radius - this.nextZoneDecrement)
|
this.nextZone.center = this.getRandomNextCenter(this.nextZone.radius - this.nextZoneDecrement)
|
||||||
//Next center cannot be found
|
//Next center cannot be found
|
||||||
if(this.nextZone.center === false) {
|
if (this.nextZone.center === false) {
|
||||||
console.log("no center")
|
console.log("no center")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -171,7 +169,7 @@ export class ZoneManager {
|
|||||||
end: JSON.parse(JSON.stringify(this.nextZone))
|
end: JSON.parse(JSON.stringify(this.nextZone))
|
||||||
})
|
})
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start a task that will run periodically updatinng the zone size, and calling the onZoneUpdate callback
|
* Start a task that will run periodically updatinng the zone size, and calling the onZoneUpdate callback
|
||||||
@@ -183,8 +181,8 @@ export class ZoneManager {
|
|||||||
this.updateIntervalId = setInterval(() => {
|
this.updateIntervalId = setInterval(() => {
|
||||||
const completed = ((new Date() - startTime) / (1000 * 60)) / this.zoneSettings.reductionDuration;
|
const completed = ((new Date() - startTime) / (1000 * 60)) / this.zoneSettings.reductionDuration;
|
||||||
this.currentZone.radius = map(completed, 0, 1, this.currentStartZone.radius, this.nextZone.radius)
|
this.currentZone.radius = map(completed, 0, 1, this.currentStartZone.radius, this.nextZone.radius)
|
||||||
this.currentZone.center.lat = map(completed,0,1, this.currentStartZone.center.lat, this.nextZone.center.lat)
|
this.currentZone.center.lat = map(completed, 0, 1, this.currentStartZone.center.lat, this.nextZone.center.lat)
|
||||||
this.currentZone.center.lng = map(completed,0,1, this.currentStartZone.center.lng, this.nextZone.center.lng)
|
this.currentZone.center.lng = map(completed, 0, 1, this.currentStartZone.center.lng, this.nextZone.center.lng)
|
||||||
this.onZoneUpdate(JSON.parse(JSON.stringify(this.currentZone)))
|
this.onZoneUpdate(JSON.parse(JSON.stringify(this.currentZone)))
|
||||||
//Zone shrinking is over
|
//Zone shrinking is over
|
||||||
if (completed >= 1) {
|
if (completed >= 1) {
|
||||||
@@ -194,6 +192,16 @@ export class ZoneManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, this.zoneSettings.updateIntervalSeconds * 1000);
|
}, this.zoneSettings.updateIntervalSeconds * 1000);
|
||||||
}
|
},
|
||||||
|
|
||||||
|
onNextZoneUpdate(newZone) {
|
||||||
|
playersBroadcast("new_zone", newZone)
|
||||||
|
secureAdminBroadcast("new_zone", newZone)
|
||||||
|
},
|
||||||
|
|
||||||
|
onZoneUpdate(zone) {
|
||||||
|
playersBroadcast("zone", zone)
|
||||||
|
secureAdminBroadcast("zone", zone)
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user