Files
traque/traque-back/zone_manager.js
2024-06-08 08:10:27 +00:00

109 lines
2.7 KiB
JavaScript

import { playersBroadcast, teamBroadcast } from './team_socket.js';
import { secureAdminBroadcast } from './admin_socket.js';
export let currentZone = []
let tileSize = 16;
export class TileNumber {
constructor(x, y) {
this.x = x;
this.y = y;
this.removeDate = null;
}
equals(other) {
return this.x === other.x && this.y === other.y;
}
removeIn(minutes) {
this.removeDate = Date.now() + 1000 * 60 * minutes
}
}
export function latLngToTileNumber(pos, tileSize) {
const numTilesX = 2 ** tileSize;
const numTilesY = 2 ** tileSize;
const lngDegrees = pos[1];
const latRadians = pos[0] * (Math.PI / 180);
return {
x:Math.round(numTilesX * ((lngDegrees + 180) / 360)),
y:Math.round(numTilesY * (1 - Math.log(Math.tan(latRadians) + 1 / Math.cos(latRadians)) / Math.PI) / 2)
};
}
export function broadcastZoneState() {
playersBroadcast("zone", currentZone);
secureAdminBroadcast("zone", currentZone);
}
/**
* Remove all tiles from the zone
*/
export function resetZone() {
currentZone = [];
broadcastZoneState();
}
export function setTileSize(size) {
resetZone();
tileSize = size;
}
/**
* Check whether a position is in the zone
* @param {Object} position The position to check
*/
export function isInZone(position) {
let tile = latLngToTileNumber(position, tileSize);
return currentZone.some(square => square.equals(tile))
}
/**
* Initialize a zone with a list of tiles
* @param {Array} zone Array of tiles to add
*/
export function initZone(zone) {
currentZone = [];
try {
for (let { x, y } of zone) {
currentZone.push(new TileNumber(x, y))
}
broadcastZoneState();
} catch (e) {
console.error(e);
secureAdminBroadcast("error", "Invalid zone format")
}
}
/**
* Put a list of tiles in a warning state for a certain amount of time, before removing them
* @param {Array} zone Array of tiles to remove
* @param {Number} time Time before those tiles get removed in minutes
*/
export function removeZone(zone, time) {
for (let tile of zone) {
for (let currentTile of currentZone) {
if (currentTile.equals(tile)) {
currentTile.removeIn(time);
}
}
}
broadcastZoneState();
}
setInterval(() => {
let changed = false;
currentZone = currentZone.map(square => {
if (square.removeDate !== null && square.removeDate < Date.now()) {
changed = true;
return null;
}
return square;
}).filter(square => square !== null)
if (changed) {
broadcastZoneState();
}
}, 1000);