Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions squad-server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ export default class SquadServer extends EventEmitter {
});

this.logParser.on('NEW_GAME', async (data) => {
data.layer = await Layers.getLayerByClassname(data.layerClassname);
await this.updateLayerInformation();
data.layer = this.currentLayer;

this.layerHistory.unshift({ layer: data.layer, time: data.time });
this.layerHistory = this.layerHistory.slice(0, this.layerHistoryMaxLength);

this.currentLayer = data.layer;
await this.updateAdmins();
this.emit('NEW_GAME', data);
});
Expand Down Expand Up @@ -505,16 +505,24 @@ export default class SquadServer extends EventEmitter {
const nextMap = await this.rcon.getNextMap();
const nextMapToBeVoted = nextMap.layer === 'To be voted';

const currentLayer = await Layers.getLayerById(currentMap.layer);
const nextLayer = nextMapToBeVoted ? null : await Layers.getLayerById(nextMap.layer);
const [currentLayer, currentTeams] =
await Layers.getLayerById(currentMap.layer,
currentMap.factionOne,
currentMap.factionTwo);
const [nextLayer, nextTeams] =
nextMapToBeVoted ? null : await Layers.getLayerById(nextMap.layer,
nextMap.factionOne,
nextMap.factionTwo);

if (this.layerHistory.length === 0) {
this.layerHistory.unshift({ layer: currentLayer, time: Date.now() });
this.layerHistory = this.layerHistory.slice(0, this.layerHistoryMaxLength);
}

this.currentLayer = currentLayer;
this.currentTeams = currentTeams;
this.nextLayer = nextLayer;
this.nextTeams = nextTeams;
this.nextLayerToBeVoted = nextMapToBeVoted;

this.emit('UPDATED_LAYER_INFORMATION');
Expand Down Expand Up @@ -543,7 +551,7 @@ export default class SquadServer extends EventEmitter {
const rawData = await this.rcon.execute(`ShowServerInfo`);
Logger.verbose('SquadServer', 3, `Server information raw data`, rawData);
const data = JSON.parse(rawData);
Logger.verbose('SquadServer', 2, `Server information data`, JSON.data);
Logger.verbose('SquadServer', 2, `Server information data`, data);

const info = {
raw: data,
Expand All @@ -561,8 +569,8 @@ export default class SquadServer extends EventEmitter {
currentLayer: data.MapName_s,
nextLayer: data.NextLayer_s,

teamOne: data.TeamOne_s?.replace(new RegExp(data.MapName_s, 'i'), '') || '',
teamTwo: data.TeamTwo_s?.replace(new RegExp(data.MapName_s, 'i'), '') || '',
teamOne: data.TeamOne_s,
teamTwo: data.TeamTwo_s,

matchTimeout: parseFloat(data.MatchTimeout_d),
matchStartTime: this.getMatchStartTimeByPlaytime(data.PLAYTIME_I),
Expand All @@ -579,13 +587,14 @@ export default class SquadServer extends EventEmitter {
this.playerCount = info.playerCount;
this.publicQueue = info.publicQueue;
this.reserveQueue = info.reserveQueue;
this.unitNames = [data.TeamOne_s, data.TeamTwo_s];

this.matchTimeout = info.matchTimeout;
this.matchStartTime = info.matchStartTime;
this.gameVersion = info.gameVersion;

if (!this.currentLayer) this.currentLayer = Layers.getLayerByClassname(info.currentLayer);
if (!this.nextLayer) this.nextLayer = Layers.getLayerByClassname(info.nextLayer);
if (!this.currentLayer)
await this.updateLayerInformation();

this.emit('UPDATED_A2S_INFORMATION', info);
this.emit('UPDATED_SERVER_INFORMATION', info);
Expand Down
28 changes: 5 additions & 23 deletions squad-server/layers/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,12 @@ export default class Layer {
this.sizeType = data.mapSizeType;
this.numberOfCapturePoints = parseInt(data.capturePoints);
this.lighting = {
name: data.lighting,
type: data.persistentLightingType,
classname: data.lightingLevel
};
this.teams = [];
for (const t of ['team1', 'team2']) {
this.teams.push({
faction: data[t].faction,
name: data[t].teamSetupName,
tickets: data[t].tickets,
commander: data[t].commander,
vehicles: (data[t].vehicles || []).map((vehicle) => ({
name: vehicle.type,
classname: vehicle.rawType,
count: vehicle.count,
spawnDelay: vehicle.delay,
respawnDelay: vehicle.respawnTime
})),
numberOfTanks: (data[t].vehicles || []).filter((v) => {
return v.icon.match(/_tank/);
}).length,
numberOfHelicopters: (data[t].vehicles || []).filter((v) => {
return v.icon.match(/helo/);
}).length
});
}
this.factions = data.factions;
this.commander = data.commander;
this.tickets = [data.teamConfigs.team1.tickets,
data.teamConfigs.team2.tickets];
}
}
51 changes: 45 additions & 6 deletions squad-server/layers/layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ class Layers {

Logger.verbose('Layers', 1, 'Pulling layers...');
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/fantinodavide/SquadLayerList/main/layers.json'
);

for (const layer of response.data.Maps) {
this.layers.push(new Layer(layer));
}
this.units = response.data.Units;

Logger.verbose('Layers', 1, `Pulled ${this.layers.length} layers.`);
Logger.verbose('Layers', 1, `Pulled ${this.layers.length} layers and ${Object.keys(this.units).length} units.`);

this.pulled = true;

Expand All @@ -45,12 +46,50 @@ class Layers {
return null;
}

getLayerById(layerId) {
return this.getLayerByCondition((layer) => layer.layerid === layerId);
convertFactionToUnit(layer, factionName, teamIndex) {
// From factionName, in format "ADF+Mechanized", return the correct
// "ADF_XX_Mechanized" for current layer.
const factionParts = factionName.split("+");
const matches = layer.factions.filter((f) =>
f.factionId === factionParts[0] &&
f.availableOnTeams.includes(teamIndex + 1)
);
if (matches.length === 1) {
const faction = matches[0];
if (factionParts.length === 1) {
return faction.defaultUnit;
}
else {
const unitParts = faction.defaultUnit.split('_', 2);
if (faction.types.includes(factionParts[1]))
return `${unitParts[0]}_${unitParts[1]}_${factionParts[1]}`;
else
return faction.defaultUnit;
}
}
}

getLayerByClassname(classname) {
return this.getLayerByCondition((layer) => layer.classname === classname);
async getLayerById(layerId, factionOne, factionTwo) {
const layer = await this.getLayerByCondition((layer) => layer.layerid === layerId);
if (layer) {
const factions = [factionOne, factionTwo];
let teams = [];
for (const teamIdx of [0, 1]) {
const faction = factions[teamIdx];
const unitName = this.convertFactionToUnit(layer, faction, teamIdx);
const unit = this.units[unitName];
teams[teamIdx] = {
faction: unit.factionID,
name: unit.displayName,
unitID: unitName,
unit: unit,
tickets: layer.tickets[teamIdx],
commander: layer.commander,
vehicles: unit.vehicles,
};
}
return [layer, teams]
}
}
}

Expand Down
15 changes: 11 additions & 4 deletions squad-server/rcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,23 @@ export default class SquadRcon extends Rcon {

async getCurrentMap() {
const response = await this.execute('ShowCurrentMap');
const match = response.match(/^Current level is ([^,]*), layer is ([^,]*)/);
return { level: match[1], layer: match[2] };
const match = response.match(/^Current level is ([^,]*), layer is ([^,]*), factions ([\w+]+) ([\w+]+)/);
return {
level: match[1],
layer: match[2],
factionOne: match[3],
factionTwo: match[4]
};
}

async getNextMap() {
const response = await this.execute('ShowNextMap');
const match = response.match(/^Next level is ([^,]*), layer is ([^,]*)/);
const match = response.match(/^Next level is ([^,]*), layer is ([^,]*), factions ([\w+]+) ([\w+]+)/);
return {
level: match ? (match[1] !== '' ? match[1] : null) : null,
layer: match ? (match[2] !== 'To be voted' ? match[2] : null) : null
layer: match ? (match[2] !== 'To be voted' ? match[2] : null) : null,
factionOne: match[3],
factionTwo: match[4]
};
}

Expand Down