SquadJS/plugins/mapvote/mapvote.js

118 lines
4.2 KiB
JavaScript
Raw Normal View History

2020-06-13 09:33:44 -05:00
import EventEmitter from 'events';
import SquadLayers from 'connectors/squad-layers';
export default class MapVote extends EventEmitter {
constructor(server, squadLayerFilter, options = {}) {
super();
this.server = server;
this.squadLayerFilter = squadLayerFilter;
this.layerVotes = {};
2020-06-14 06:53:38 -05:00
this.layerVoteTimes = {};
2020-06-13 09:33:44 -05:00
this.playerVotes = {};
this.currentWinner = null;
this.minVoteCount = options.minVoteCount || null;
}
addVote(identifier, layerName) {
if (this.layerVotes[layerName]) {
this.layerVotes[layerName] += 1;
} else {
this.layerVotes[layerName] = 1;
2020-06-14 06:53:38 -05:00
this.layerVoteTimes[layerName] = new Date();
2020-06-13 09:33:44 -05:00
}
this.playerVotes[identifier] = layerName;
}
removeVote(identifier) {
if (!this.playerVotes[identifier]) return;
if (this.layerVotes[this.playerVotes[identifier]])
this.layerVotes[this.playerVotes[identifier]] -= 1;
2020-06-14 06:53:38 -05:00
if (this.layerVotes[this.playerVotes[identifier]] === 0) {
2020-06-13 09:33:44 -05:00
delete this.layerVotes[this.playerVotes[identifier]];
2020-06-14 06:53:38 -05:00
delete this.layerVoteTimes[this.playerVotes[identifier]];
}
2020-06-13 09:33:44 -05:00
delete this.playerVotes[identifier];
}
getResults(applyMinVoteCount = false) {
if (
!applyMinVoteCount ||
this.minVoteCount === null ||
Object.keys(this.playerVotes).length >= this.minVoteCount
) {
return Object.keys(this.layerVotes)
.map(layerName => ({
layer: this.squadLayerFilter.getLayerByLayerName(layerName),
votes: this.layerVotes[layerName]
}))
.sort((a, b) => {
if (a.votes > b.votes) return -1;
if (a.votes < b.votes) return 1;
2020-06-14 06:53:38 -05:00
return this.layerVoteTimes[a.layer.layer] < this.layerVoteTimes[b.layer.layer] ? -1 : 1;
2020-06-13 09:33:44 -05:00
});
} else return [];
}
async makeVote(identifier, layer) {
layer = SquadLayers.getLayerByLayerName(layer);
if (!this.squadLayerFilter.inLayerPool(layer))
throw new Error(`${layer.layer} is not in layer pool.`);
if (!this.squadLayerFilter.isLayerHistoryCompliant(this.server, layer))
throw new Error(`${layer.layer} was played too recently.`);
if (!this.squadLayerFilter.isMapHistoryCompliant(this.server, layer))
throw new Error(`${layer.map} was played too recently.`);
if (!this.squadLayerFilter.isGamemodeHistoryCompliant(this.server, layer))
throw new Error(`${layer.gamemode} was played too recently.`);
2020-06-14 06:53:38 -05:00
if (!this.squadLayerFilter.isGamemodeRepetitiveCompliant(this.server, layer))
throw new Error(`${layer.gamemode} has been played too much recently.`);
if (!this.squadLayerFilter.isFactionCompliant(this.server, layer))
throw new Error('Cannot be played as one team will remain the same faction.');
if (!this.squadLayerFilter.isFactionHistoryCompliant(this.server, layer))
throw new Error(
`Cannot be played as either ${layer.teamOne.faction} or ${layer.teamTwo.faction} has been played too recently.`
);
if (!this.squadLayerFilter.isFactionRepetitiveCompliant(this.server, layer))
throw new Error(
`Cannot be played as either ${layer.teamOne.faction} or ${layer.teamTwo.faction} has been played too much recently.`
);
2020-06-13 09:33:44 -05:00
if (!this.squadLayerFilter.isPlayerCountCompliant(this.server, layer))
throw new Error(
`${layer.layer} is only suitable for a player count between ${layer.estimatedSuitablePlayerCount.min} and ${layer.estimatedSuitablePlayerCount.max}.`
);
this.removeVote(identifier);
this.addVote(identifier, layer.layer);
const results = this.getResults(true);
if (results.length > 0) {
2020-06-14 06:53:38 -05:00
if (results[0].layer.layer !== this.currentWinner) {
2020-06-13 11:35:00 -05:00
await this.server.rcon.execute(`AdminSetNextMap ${results[0].layer.layer}`);
2020-06-13 09:33:44 -05:00
this.emit('NEW_WINNER', results);
2020-06-14 06:53:38 -05:00
this.currentWinner = results[0].layer.layer;
2020-06-13 09:33:44 -05:00
}
}
return layer.layer;
}
async makeVoteByDidYouMean(identifier, layerName) {
const layer = SquadLayers.getLayerByDidYouMean(layerName);
if (layer === null) throw new Error(`${layerName} is not a Squad layer.`);
return this.makeVote(identifier, layer.layer);
}
async makeVoteByNumber(identifier, number) {
const layer = this.squadLayerFilter.getLayerByNumber(number);
return this.makeVote(identifier, layer.layer);
}
}