mirror of
https://git.rezel.net/LudoTech/traque.git
synced 2026-02-09 02:10:18 +01:00
Merge branch 'main' of github.com:quentinrsl/traque
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { io, game } from "./index.js";
|
import { io, game, penaltyController } from "./index.js";
|
||||||
import { playersBroadcast, sendUpdatedTeamInformations } from "./team_socket.js";
|
import { playersBroadcast, sendUpdatedTeamInformations } from "./team_socket.js";
|
||||||
|
|
||||||
import { config } from "dotenv";
|
import { config } from "dotenv";
|
||||||
@@ -45,6 +45,8 @@ export function initAdminSocketHandler() {
|
|||||||
//Send the current state
|
//Send the current state
|
||||||
socket.emit("game_state", game.state)
|
socket.emit("game_state", game.state)
|
||||||
//Other settings that need initialization
|
//Other settings that need initialization
|
||||||
|
socket.emit("penalty_settings", penaltyController.settings)
|
||||||
|
socket.emit("game_settings", game.settings)
|
||||||
socket.emit("zone_settings", game.zone.zoneSettings)
|
socket.emit("zone_settings", game.zone.zoneSettings)
|
||||||
socket.emit("zone", game.zone.currentZone)
|
socket.emit("zone", game.zone.currentZone)
|
||||||
socket.emit("new_zone", {
|
socket.emit("new_zone", {
|
||||||
@@ -58,6 +60,18 @@ export function initAdminSocketHandler() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on("set_game_settings", (settings) => {
|
||||||
|
if (!loggedIn) {
|
||||||
|
socket.emit("error", "Not logged in");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!game.changeSettings(settings)) {
|
||||||
|
socket.emit("error", "Invalid settings");
|
||||||
|
}
|
||||||
|
secureAdminBroadcast("game_settings",game.settings);
|
||||||
|
playersBroadcast("game_settings", game.settings);
|
||||||
|
})
|
||||||
|
|
||||||
socket.on("set_zone_settings", (settings) => {
|
socket.on("set_zone_settings", (settings) => {
|
||||||
if (!loggedIn) {
|
if (!loggedIn) {
|
||||||
socket.emit("error", "Not logged in");
|
socket.emit("error", "Not logged in");
|
||||||
@@ -72,6 +86,20 @@ export function initAdminSocketHandler() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
socket.on("set_penalty_settings", (settings) => {
|
||||||
|
if (!loggedIn) {
|
||||||
|
socket.emit("error", "Not logged in");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!penaltyController.updateSettings(settings)) {
|
||||||
|
socket.emit("error", "Invalid settings");
|
||||||
|
socket.emit("penalty_settings", penaltyController.settings)
|
||||||
|
}else {
|
||||||
|
secureAdminBroadcast("penalty_settings", penaltyController.settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
//User is attempting to add a new team
|
//User is attempting to add a new team
|
||||||
socket.on("add_team", (teamName) => {
|
socket.on("add_team", (teamName) => {
|
||||||
if (!loggedIn) {
|
if (!loggedIn) {
|
||||||
|
|||||||
@@ -16,6 +16,17 @@ export default class Game {
|
|||||||
this.teams = [];
|
this.teams = [];
|
||||||
this.state = GameState.SETUP;
|
this.state = GameState.SETUP;
|
||||||
this.zone = new ZoneManager(onUpdateZone, onUpdateNewZone)
|
this.zone = new ZoneManager(onUpdateZone, onUpdateNewZone)
|
||||||
|
this.settings = {
|
||||||
|
loserEndGameMessage: "",
|
||||||
|
winnerEndGameMessage: "",
|
||||||
|
capturedMessage: "",
|
||||||
|
waitingMessage: "Jeu en préparation, veuillez patienter."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSettings(newSettings) {
|
||||||
|
this.settings = {...this.settings, ...newSettings};
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(newState) {
|
setState(newState) {
|
||||||
@@ -31,7 +42,7 @@ export default class Game {
|
|||||||
this.initLastSentLocations();
|
this.initLastSentLocations();
|
||||||
this.zone.reset()
|
this.zone.reset()
|
||||||
//If the zone cannot be setup, reset everything
|
//If the zone cannot be setup, reset everything
|
||||||
if(!this.zone.start()) {
|
if (!this.zone.start()) {
|
||||||
this.setState(GameState.SETUP);
|
this.setState(GameState.SETUP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -41,10 +52,14 @@ export default class Game {
|
|||||||
penaltyController.stop();
|
penaltyController.stop();
|
||||||
}
|
}
|
||||||
//Game reset
|
//Game reset
|
||||||
if(newState == GameState.SETUP) {
|
if (newState == GameState.SETUP) {
|
||||||
for(let team of this.teams) {
|
for (let team of this.teams) {
|
||||||
team.penalties = 0;
|
team.penalties = 0;
|
||||||
team.captured = false;
|
team.captured = false;
|
||||||
|
team.enemyLocation = null;
|
||||||
|
team.enemyName = null;
|
||||||
|
team.currentLocation = null;
|
||||||
|
team.lastSentLocation = null;
|
||||||
}
|
}
|
||||||
this.updateTeamChasing();
|
this.updateTeamChasing();
|
||||||
}
|
}
|
||||||
@@ -99,7 +114,7 @@ export default class Game {
|
|||||||
|
|
||||||
updateTeamChasing() {
|
updateTeamChasing() {
|
||||||
if (this.playingTeamCount() <= 2) {
|
if (this.playingTeamCount() <= 2) {
|
||||||
if(this.state == GameState.PLAYING) {
|
if (this.state == GameState.PLAYING) {
|
||||||
this.finishGame()
|
this.finishGame()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -143,6 +158,7 @@ export default class Game {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.updateTeamChasing();
|
this.updateTeamChasing();
|
||||||
|
penaltyController.checkPenalties();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +180,7 @@ export default class Game {
|
|||||||
initLastSentLocations() {
|
initLastSentLocations() {
|
||||||
for (let team of this.teams) {
|
for (let team of this.teams) {
|
||||||
team.lastSentLocation = team.currentLocation;
|
team.lastSentLocation = team.currentLocation;
|
||||||
team.locationSendDeadline = Number(new Date()) + process.env.ALLOWED_TIME_BETWEEN_POSITION_UPDATE_IN_MINUTES * 60 * 1000;
|
team.locationSendDeadline = Number(new Date()) + penaltyController.settings.allowedTimeBetweenPositionUpdate * 60 * 1000;
|
||||||
sendUpdatedTeamInformations(team.id);
|
sendUpdatedTeamInformations(team.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +190,7 @@ export default class Game {
|
|||||||
if (team == undefined) {
|
if (team == undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
team.locationSendDeadline = Number(new Date()) + process.env.ALLOWED_TIME_BETWEEN_POSITION_UPDATE_IN_MINUTES * 60 * 1000;
|
team.locationSendDeadline = Number(new Date()) + penaltyController.settings.allowedTimeBetweenPositionUpdate * 60 * 1000;
|
||||||
team.lastSentLocation = team.currentLocation;
|
team.lastSentLocation = team.currentLocation;
|
||||||
if (this.getTeam(team.chasing) != null) {
|
if (this.getTeam(team.chasing) != null) {
|
||||||
team.enemyLocation = this.getTeam(team.chasing).lastSentLocation;
|
team.enemyLocation = this.getTeam(team.chasing).lastSentLocation;
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { config } from "dotenv";
|
|
||||||
import { getDistanceFromLatLon, isInCircle } from "./map_utils.js";
|
import { getDistanceFromLatLon, 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 { GameState } from "./game.js";
|
||||||
import { secureAdminBroadcast } from "./admin_socket.js";
|
import { secureAdminBroadcast } from "./admin_socket.js";
|
||||||
import { game } from "./index.js";
|
import { game } from "./index.js";
|
||||||
config()
|
|
||||||
|
|
||||||
export class PenaltyController {
|
export class PenaltyController {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -12,75 +10,100 @@ export class PenaltyController {
|
|||||||
this.game = game;
|
this.game = game;
|
||||||
this.outOfBoundsSince = {};
|
this.outOfBoundsSince = {};
|
||||||
this.checkIntervalId = null;
|
this.checkIntervalId = null;
|
||||||
|
this.settings = {
|
||||||
|
allowedTimeOutOfZone: 10,
|
||||||
|
allowedTimeBetweenPositionUpdate: 10,
|
||||||
|
maxPenalties: 3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.outOfBoundsSince = {};
|
this.outOfBoundsSince = {};
|
||||||
if(this.checkIntervalId) {
|
if (this.checkIntervalId) {
|
||||||
clearInterval(this.checkIntervalId)
|
clearInterval(this.checkIntervalId)
|
||||||
}
|
}
|
||||||
//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 (this.game.state == GameState.PLAYING) {
|
||||||
this.watchPositionUpdate();
|
this.watchPositionUpdate();
|
||||||
this.watchZone();
|
this.watchZone();
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
stop(){
|
stop() {
|
||||||
this.outOfBoundsSince = {};
|
this.outOfBoundsSince = {};
|
||||||
if(this.checkIntervalId) {
|
if (this.checkIntervalId) {
|
||||||
clearInterval(this.checkIntervalId)
|
clearInterval(this.checkIntervalId)
|
||||||
this.checkIntervalId = null;
|
this.checkIntervalId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSettings(newSettings) {
|
||||||
|
//Sanitize input
|
||||||
|
if (newSettings.maxPenalties && (isNaN(parseInt(newSettings.maxPenalties)) || newSettings.maxPenalties < 0)) { return false }
|
||||||
|
if (newSettings.allowedTimeBetweenPositionUpdate && (isNaN(parseFloat(newSettings.allowedTimeBetweenPositionUpdate)) || newSettings.allowedTimeBetweenPositionUpdate < 0)) { return false }
|
||||||
|
if (newSettings.allowedTimeOutOfZone && (isNaN(parseFloat(newSettings.allowedTimeOutOfZone)) || newSettings.allowedTimeOutOfZone < 0)) { return false }
|
||||||
|
|
||||||
|
this.settings = { ...this.settings, ...newSettings };
|
||||||
|
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 = this.game.getTeam(teamId);
|
||||||
if(!team) {
|
if (!team) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (team.captured) {
|
if (team.captured) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
team.penalties++;
|
team.penalties++;
|
||||||
if (team.penalties >= process.env.MAX_PENALTIES) {
|
if (team.penalties >= this.settings.maxPenalties) {
|
||||||
this.game.capture(team.id);
|
this.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)")
|
||||||
teamBroadcast(team.chased, "success", "The team you were chasing has been eliminated")
|
teamBroadcast(team.chased, "success", "The team you were chasing has been eliminated")
|
||||||
} else {
|
} else {
|
||||||
teamBroadcast(teamId, "warning", `You recieved a penalty (${team.penalties}/${process.env.MAX_PENALTIES})`)
|
teamBroadcast(teamId, "warning", `You recieved a penalty (${team.penalties}/${this.settings.maxPenalties})`)
|
||||||
sendUpdatedTeamInformations(teamId);
|
sendUpdatedTeamInformations(teamId);
|
||||||
}
|
}
|
||||||
secureAdminBroadcast("teams", this.game.teams)
|
secureAdminBroadcast("teams", this.game.teams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkPenalties() {
|
||||||
|
for (let team of game.teams) {
|
||||||
|
if (team.penalties >= this.settings.maxPenalties) {
|
||||||
|
this.game.capture(team.id);
|
||||||
|
sendUpdatedTeamInformations(teamId);
|
||||||
|
sendUpdatedTeamInformations(team.chased);
|
||||||
|
teamBroadcast(teamId, "warning", "You have been eliminated (reason: too many penalties)")
|
||||||
|
teamBroadcast(team.chased, "success", "The team you were chasing has been eliminated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
watchZone() {
|
watchZone() {
|
||||||
console.log("watching zone")
|
|
||||||
this.game.teams.forEach((team) => {
|
this.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 || this.game.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] }, this.game.zone.currentZone.center, this.game.zone.currentZone.radius)) {
|
||||||
console.log("tema " + team.name + " out of zone")
|
|
||||||
//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();
|
||||||
console.log("tema " + team.name + " warned")
|
teamBroadcast(team.id, "warning", `You left the zone, you have ${this.settings.allowedTimeOutOfZone} minutes to get back in the marked area.`)
|
||||||
teamBroadcast(team.id, "warning", `You left the zone, you have ${process.env.ALLOWED_TIME_OUT_OF_ZONE_IN_MINUTES} minutes to get back in the marked area.`)
|
} else if (new Date() - this.outOfBoundsSince[team.id] > this.settings.allowedTimeOutOfZone * 60 * 1000) {
|
||||||
} else {
|
this.addPenalty(team.id)
|
||||||
if (new Date() - this.outOfBoundsSince[team.id] > process.env.ALLOWED_TIME_OUT_OF_ZONE_IN_MINUTES * 60 * 1000) {
|
this.outOfBoundsSince[team.id] = new Date();
|
||||||
this.addPenalty(team.id)
|
} else if (Math.abs(new Date() - this.outOfBoundsSince[team.id] - (this.settings.allowedTimeOutOfZone - 1) * 60 * 1000) < 100) {
|
||||||
this.outOfBoundsSince[team.id] = new Date();
|
teamBroadcast(team.id, "warning", `You left the zone, you have 1 minutes to get back in the marked area.`)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.outOfBoundsSince[team.id]) {
|
if (this.outOfBoundsSince[team.id]) {
|
||||||
@@ -90,12 +113,13 @@ export class PenaltyController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
watchPositionUpdate() {
|
watchPositionUpdate() {
|
||||||
this.game.teams.forEach((team) => {
|
this.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) {
|
||||||
team.locationSendDeadline = Number(new Date()) + process.env.ALLOWED_TIME_BETWEEN_POSITION_UPDATE_IN_MINUTES * 60 * 1000;
|
team.locationSendDeadline = Number(new Date()) + this.settings.allowedTimeBetweenPositionUpdate * 60 * 1000;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (new Date() > team.locationSendDeadline) {
|
if (new Date() > team.locationSendDeadline) {
|
||||||
@@ -103,6 +127,8 @@ export class PenaltyController {
|
|||||||
this.game.sendLocation(team.id);
|
this.game.sendLocation(team.id);
|
||||||
sendUpdatedTeamInformations(team.id);
|
sendUpdatedTeamInformations(team.id);
|
||||||
secureAdminBroadcast("teams", this.game.teams)
|
secureAdminBroadcast("teams", this.game.teams)
|
||||||
|
}else if(Math.abs(new Date() - team.locationSendDeadline - 60 * 1000) < 100) {
|
||||||
|
teamBroadcast(team.id, "warning", `You have one minute left to udpate your location.`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ export function initTeamSocket() {
|
|||||||
sendUpdatedTeamInformations(loginTeamId);
|
sendUpdatedTeamInformations(loginTeamId);
|
||||||
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("zone", game.zone.currentZone)
|
socket.emit("zone", game.zone.currentZone)
|
||||||
socket.emit("new_zone", {
|
socket.emit("new_zone", {
|
||||||
begin: game.zone.currentStartZone,
|
begin: game.zone.currentStartZone,
|
||||||
@@ -111,6 +112,7 @@ export function initTeamSocket() {
|
|||||||
}
|
}
|
||||||
game.updateTeamChasing();
|
game.updateTeamChasing();
|
||||||
teamBroadcast(teamId, "update_team", { enemyLocation: team.enemyLocation,locationSendDeadline: team.locationSendDeadline });
|
teamBroadcast(teamId, "update_team", { enemyLocation: team.enemyLocation,locationSendDeadline: team.locationSendDeadline });
|
||||||
|
teamBroadcast(teamId,"success", "Position udpated")
|
||||||
secureAdminBroadcast("teams", game.teams)
|
secureAdminBroadcast("teams", game.teams)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user