properly get a list of layers

This commit is contained in:
Skillet 2023-04-26 07:08:14 -04:00
parent 52a1317c91
commit adf3e01d11
4 changed files with 169 additions and 56 deletions

View File

@ -307,6 +307,28 @@ Interested in creating your own plugin? [See more here](./squad-server/plugins/r
]</code></pre></li></ul> ]</code></pre></li></ul>
</details> </details>
<details>
<summary>DBLogPlayerTime</summary>
<h2>DBLogPlayerTime</h2>
<p>replacement add-on to dblog for player join/seeding times</p>
<h3>Options</h3>
<ul><li><h4>database (Required)</h4>
<h6>Description</h6>
<p>The Sequelize connector to log server information to.</p>
<h6>Default</h6>
<pre><code>mysql</code></pre></li>
<li><h4>overrideServerID</h4>
<h6>Description</h6>
<p>A overridden server ID.</p>
<h6>Default</h6>
<pre><code>null</code></pre></li>
<li><h4>seedingThreshold</h4>
<h6>Description</h6>
<p>seeding Threshold.</p>
<h6>Default</h6>
<pre><code>50</code></pre></li></ul>
</details>
<details> <details>
<summary>DBLog</summary> <summary>DBLog</summary>
<h2>DBLog</h2> <h2>DBLog</h2>

View File

@ -77,6 +77,13 @@
} }
] ]
}, },
{
"plugin": "DBLogPlayerTime",
"enabled": false,
"database": "mysql",
"overrideServerID": null,
"seedingThreshold": 50
},
{ {
"plugin": "DBLog", "plugin": "DBLog",
"enabled": false, "enabled": false,

View File

@ -63,9 +63,9 @@ export default class SquadServer extends EventEmitter {
async watch() { async watch() {
Logger.verbose( Logger.verbose(
'SquadServer', 'SquadServer',
1, 1,
`Beginning to watch ${this.options.host}:${this.options.queryPort}...` `Beginning to watch ${this.options.host}:${this.options.queryPort}...`
); );
await Layers.pull(); await Layers.pull();
@ -73,6 +73,7 @@ export default class SquadServer extends EventEmitter {
this.admins = await fetchAdminLists(this.options.adminLists); this.admins = await fetchAdminLists(this.options.adminLists);
await this.rcon.connect(); await this.rcon.connect();
await this.updateLayerList();
await this.logParser.watch(); await this.logParser.watch();
await this.updateSquadList(); await this.updateSquadList();
@ -176,11 +177,11 @@ export default class SquadServer extends EventEmitter {
setupLogParser() { setupLogParser() {
this.logParser = new LogParser( this.logParser = new LogParser(
Object.assign(this.options.ftp, { Object.assign(this.options.ftp, {
mode: this.options.logReaderMode, mode: this.options.logReaderMode,
logDir: this.options.logDir, logDir: this.options.logDir,
host: this.options.ftp.host || this.options.host host: this.options.ftp.host || this.options.host
}) })
); );
this.logParser.on('ADMIN_BROADCAST', (data) => { this.logParser.on('ADMIN_BROADCAST', (data) => {
@ -222,19 +223,18 @@ export default class SquadServer extends EventEmitter {
layer: datalayer layer: datalayer
}; };
this.emit("ROUND_ENDED", outdata); this.emit('ROUND_ENDED', outdata);
}) });
this.logParser.on('PLAYER_CONNECTED', async (data) => { this.logParser.on('PLAYER_CONNECTED', async (data) => {
data.player = await this.getPlayerBySteamID(data.steamID); data.player = await this.getPlayerBySteamID(data.steamID);
if (data.player) { if (data.player) {
data.player.suffix = data.playerSuffix; data.player.suffix = data.playerSuffix;
} } else {
else{
data.player = { data.player = {
steamID: data.steamID, steamID: data.steamID,
name: data.playerSuffix name: data.playerSuffix
} };
} }
this.emit('PLAYER_CONNECTED', data); this.emit('PLAYER_CONNECTED', data);
@ -242,10 +242,10 @@ export default class SquadServer extends EventEmitter {
this.logParser.on('PLAYER_DISCONNECTED', async (data) => { this.logParser.on('PLAYER_DISCONNECTED', async (data) => {
data.player = await this.getPlayerBySteamID(data.steamID); data.player = await this.getPlayerBySteamID(data.steamID);
if(!data.player){ if (!data.player) {
data.player = { data.player = {
steamID: data.steamID steamID: data.steamID
} };
} }
this.emit('PLAYER_DISCONNECTED', data); this.emit('PLAYER_DISCONNECTED', data);
@ -257,8 +257,8 @@ export default class SquadServer extends EventEmitter {
if (data.victim && data.attacker) if (data.victim && data.attacker)
data.teamkill = data.teamkill =
data.victim.teamID === data.attacker.teamID && data.victim.teamID === data.attacker.teamID &&
data.victim.steamID !== data.attacker.steamID; data.victim.steamID !== data.attacker.steamID;
delete data.victimName; delete data.victimName;
delete data.attackerName; delete data.attackerName;
@ -269,12 +269,13 @@ export default class SquadServer extends EventEmitter {
this.logParser.on('PLAYER_WOUNDED', async (data) => { this.logParser.on('PLAYER_WOUNDED', async (data) => {
data.victim = await this.getPlayerByName(data.victimName); data.victim = await this.getPlayerByName(data.victimName);
data.attacker = await this.getPlayerByName(data.attackerName); data.attacker = await this.getPlayerByName(data.attackerName);
if(!data.attacker) data.attacker = await this.getPlayerByController(data.attackerPlayerController); if (!data.attacker)
data.attacker = await this.getPlayerByController(data.attackerPlayerController);
if (data.victim && data.attacker) if (data.victim && data.attacker)
data.teamkill = data.teamkill =
data.victim.teamID === data.attacker.teamID && data.victim.teamID === data.attacker.teamID &&
data.victim.steamID !== data.attacker.steamID; data.victim.steamID !== data.attacker.steamID;
this.emit('PLAYER_WOUNDED', data); this.emit('PLAYER_WOUNDED', data);
if (data.teamkill) this.emit('TEAMKILL', data); if (data.teamkill) this.emit('TEAMKILL', data);
@ -284,12 +285,13 @@ export default class SquadServer extends EventEmitter {
console.log(data); console.log(data);
data.victim = await this.getPlayerByName(data.victimName); data.victim = await this.getPlayerByName(data.victimName);
data.attacker = await this.getPlayerByName(data.attackerName); data.attacker = await this.getPlayerByName(data.attackerName);
if(!data.attacker) data.attacker = await this.getPlayerByController(data.attackerPlayerController); if (!data.attacker)
data.attacker = await this.getPlayerByController(data.attackerPlayerController);
if (data.victim && data.attacker) if (data.victim && data.attacker)
data.teamkill = data.teamkill =
data.victim.teamID === data.attacker.teamID && data.victim.teamID === data.attacker.teamID &&
data.victim.steamID !== data.attacker.steamID; data.victim.steamID !== data.attacker.steamID;
console.log(data); console.log(data);
@ -370,13 +372,15 @@ export default class SquadServer extends EventEmitter {
} }
const players = []; const players = [];
for (const player of await this.rcon.getListPlayers()){ for (const player of await this.rcon.getListPlayers()) {
players.push({ players.push({
...oldPlayerInfo[player.steamID], ...oldPlayerInfo[player.steamID],
...player, ...player,
playercont: this.logParser.eventStore.players[player.steamID] ? this.logParser.eventStore.players[player.steamID].controller : null, playercont: this.logParser.eventStore.players[player.steamID]
squad: await this.getSquadByID(player.teamID, player.squadID) ? this.logParser.eventStore.players[player.steamID].controller
}); : null,
squad: await this.getSquadByID(player.teamID, player.squadID)
});
} }
this.players = players; this.players = players;
@ -440,9 +444,10 @@ export default class SquadServer extends EventEmitter {
const nextMapToBeVoted = nextMap.layer === 'To be voted'; const nextMapToBeVoted = nextMap.layer === 'To be voted';
let currentLayer = await Layers.getLayerByName(currentMap.layer); let currentLayer = await Layers.getLayerByName(currentMap.layer);
if(!currentLayer) currentLayer = await Layers.getLayerById(currentMap.layer); if (!currentLayer) currentLayer = await Layers.getLayerById(currentMap.layer);
if(!currentLayer){ if (!currentLayer) {
if(currentMap.level === "Jensens") currentLayer = await Layers.getLayerByName("Jensen's Training Range"); if (currentMap.level === 'Jensens')
currentLayer = await Layers.getLayerByName("Jensen's Training Range");
} }
const nextLayer = nextMapToBeVoted ? null : await Layers.getLayerByName(nextMap.layer); const nextLayer = nextMapToBeVoted ? null : await Layers.getLayerByName(nextMap.layer);
@ -464,8 +469,8 @@ export default class SquadServer extends EventEmitter {
Logger.verbose('SquadServer', 1, `Updated layer information.`); Logger.verbose('SquadServer', 1, `Updated layer information.`);
this.updateLayerInformationTimeout = setTimeout( this.updateLayerInformationTimeout = setTimeout(
this.updateLayerInformation, this.updateLayerInformation,
this.updateLayerInformationInterval this.updateLayerInformationInterval
); );
} }
@ -518,11 +523,88 @@ export default class SquadServer extends EventEmitter {
Logger.verbose('SquadServer', 1, `Updated A2S information.`); Logger.verbose('SquadServer', 1, `Updated A2S information.`);
this.updateA2SInformationTimeout = setTimeout( this.updateA2SInformationTimeout = setTimeout(
this.updateA2SInformation, this.updateA2SInformation,
this.updateA2SInformationInterval this.updateA2SInformationInterval
); );
} }
async updateLayerList() {
// update expected list from http source
await Layers.pull();
// grab layers actually available through rcon
const rconRaw = (await this.server.rcon.execute('ListLayers'))?.split('\n') || [];
// take out first result, not actual layer just a header
rconRaw.shift();
// filter out raw result from RCON, modded layers have a suffix that needs filtering
const rconLayers = [];
for (const raw of rconRaw) {
rconLayers.push(raw.split(' ')[0]);
}
// go through http layers and delete any that don't show up in rcon
for (const layer of Layers.layers) {
if (!rconLayers.find((e) => e === layer.layerid)) Layers._layers.delete(layer.layerid);
}
// add layers that are in RCON that we did not find in the http list
for (const layer of rconLayers) {
if (!Layers.layers.find((e) => e?.layerid === layer)) {
const newLayer = this.mapLayer(layer);
if (!newLayer) continue;
Layers._layers.set(newLayer.layerid, newLayer);
}
}
}
// helper for updateLayerList
mapLayer(layid) {
layid = layid.replace(/[^a-z_\d]/gi, '');
const gl =
/((?<mod>[a-zA-Z0-9]+)_)?(?<level>[a-zA-Z0-9]+)_(?<gamemode>[a-zA-Z0-9]+)_(?<version>[a-zA-Z0-9]+)(_(?<team1>[a-zA-Z0-9]+)v(?<team2>[a-zA-Z0-9]+))?/.exec(
layid
)?.groups;
if (!gl) return;
const teams = [];
// eslint-disable-next-line no-unused-vars
for (const t of ['team1', 'team2']) {
teams.push({
tickets: 0,
commander: false,
vehicles: [],
numberOfTanks: 0,
numberOfHelicopters: 0
});
}
teams[0].faction = gl.team1 ? gl.team1 : 'Unknown';
teams[0].name = gl.team1 ? gl.team1 : 'Unknown';
teams[1].faction = gl.team2 ? gl.team2 : 'Unknown';
teams[1].name = gl.team2 ? gl.team2 : 'Unknown';
return {
name: layid.replace(/_/g, ' '),
classname: gl.level,
layerid: layid,
map: {
name: gl.level
},
gamemode: gl.gamemode,
gamemodeType: gl.gamemode,
version: gl.version,
size: '0.0x0.0 km',
sizeType: 'Playable Area',
numberOfCapturePoints: 0,
lighting: {
name: 'Unknown',
classname: 'Unknown'
},
teams: teams
};
}
async getPlayerByCondition(condition, forceUpdate = false, retry = true) { async getPlayerByCondition(condition, forceUpdate = false, retry = true) {
let matches; let matches;
@ -562,7 +644,7 @@ export default class SquadServer extends EventEmitter {
async getSquadByID(teamID, squadID) { async getSquadByID(teamID, squadID) {
if (squadID === null) return null; if (squadID === null) return null;
return this.getSquadByCondition( return this.getSquadByCondition(
(squad) => squad.teamID === teamID && squad.squadID === squadID (squad) => squad.teamID === teamID && squad.squadID === squadID
); );
} }
@ -578,7 +660,7 @@ export default class SquadServer extends EventEmitter {
return this.getPlayerByCondition((player) => player.suffix === suffix, forceUpdate, false); return this.getPlayerByCondition((player) => player.suffix === suffix, forceUpdate, false);
} }
async getPlayerByController(controller, forceUpdate){ async getPlayerByController(controller, forceUpdate) {
return this.getPlayerByCondition((player) => player.playercont === controller, forceUpdate); return this.getPlayerByCondition((player) => player.playercont === controller, forceUpdate);
} }
@ -615,15 +697,15 @@ export default class SquadServer extends EventEmitter {
if (data.error) if (data.error)
Logger.verbose( Logger.verbose(
'SquadServer', 'SquadServer',
1, 1,
`Successfully pinged the SquadJS API. Got back error: ${data.error}` `Successfully pinged the SquadJS API. Got back error: ${data.error}`
); );
else else
Logger.verbose( Logger.verbose(
'SquadServer', 'SquadServer',
1, 1,
`Successfully pinged the SquadJS API. Got back message: ${data.message}` `Successfully pinged the SquadJS API. Got back message: ${data.message}`
); );
} catch (err) { } catch (err) {
Logger.verbose('SquadServer', 1, 'Failed to ping the SquadJS API: ', err.message); Logger.verbose('SquadServer', 1, 'Failed to ping the SquadJS API: ', err.message);

View File

@ -10,9 +10,9 @@ class Layers {
this.pulled = false; this.pulled = false;
} }
get layers(){ get layers() {
return [...this._layers.values()] return [...this._layers.values()];
} }
async pull(force = false) { async pull(force = false) {
@ -25,13 +25,15 @@ class Layers {
this._layers = new Map(); this._layers = new Map();
Logger.verbose('Layers', 1, 'Pulling layers...'); Logger.verbose('Layers', 1, 'Pulling layers...');
const response = await axios.post( // Change get to post for mod support const response = await axios.post(
'http://hub.afocommunity.com/api/layers.json', [0, 1959152751] // Change get to post for mod support
'http://hub.afocommunity.com/api/layers.json',
[0, 2891780963, 1959152751, 2428425228]
); );
// const response = await axios.get( // const response = await axios.get(
// 'https://raw.githubusercontent.com/Squad-Wiki/squad-wiki-pipeline-map-data/master/completed_output/_Current%20Version/finished.json' // 'https://raw.githubusercontent.com/Squad-Wiki/squad-wiki-pipeline-map-data/master/completed_output/_Current%20Version/finished.json'
// ); // );
for (const layer of response.data.Maps) { for (const layer of response.data.Maps) {
const newLayer = new Layer(layer); const newLayer = new Layer(layer);
@ -53,8 +55,8 @@ class Layers {
return null; return null;
} }
async getLayerById(layerId){ async getLayerById(layerId) {
await this.pull(); await this.pull();
return this._layers.get(layerId) ?? null; return this._layers.get(layerId) ?? null;
} }