From 537fb2948c08e315423280c23fe7306f12c38b56 Mon Sep 17 00:00:00 2001 From: Luis Martin Schick Date: Sun, 13 Sep 2020 12:29:27 +0200 Subject: [PATCH] skipmap-plugin done --- README.md | 42 +++++++++++++ config.json | 11 ++++ plugins/index.js | 4 +- plugins/skipmap/index.js | 130 ++++++++++++++++++++++++++++++++------- 4 files changed, 163 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 4d4a07e..26a686d 100644 --- a/README.md +++ b/README.md @@ -655,6 +655,48 @@ Grafana:
Live
+
+ skipmap +

skipmap

+

The `skipmap` plugin will allow players to vote via `+/-` if they wish to skip the map

+

Options

+

command (Required)

+
Description
+

The name of the command to be used in chat.

+
Default
+
!skipmap
+

voteDuration

+
Description
+

How long the vote should go.

+
Default
+
300000
+

startTimer

+
Description
+

Time to wait before allowing the vote to go through.

+
Default
+
900000
+

pastVoteTimer

+
Description
+

Time that needs to have passed since the last vote.

+
Default
+
600000
+

endTimer

+
Description
+

Time before the end timer of the round where the votes are no longer valid.

+
Default
+
900000
+

minimumVotes

+
Description
+

The minimum required amount of votes for the vote to go through

+
Default
+
20
+

reminderInterval

+
Description
+

The time between individual reminders.

+
Default
+
120000
+
+
team-randomizer

team-randomizer

diff --git a/config.json b/config.json index 165565c..b7d104d 100644 --- a/config.json +++ b/config.json @@ -188,6 +188,17 @@ "liveThreshold": 2, "liveMessage": "Live" }, + { + "plugin": "skipmap", + "enabled": true, + "command": "!skipmap", + "voteDuration": 300000, + "startTimer": 900000, + "pastVoteTimer": 600000, + "endTimer": 900000, + "minimumVotes": 20, + "reminderInterval": 120000 + }, { "plugin": "team-randomizer", "enabled": true, diff --git a/plugins/index.js b/plugins/index.js index 0072718..263f345 100644 --- a/plugins/index.js +++ b/plugins/index.js @@ -12,10 +12,10 @@ import mapvote123 from './mapvote/mapvote-123.js'; import mapvoteDidYouMean from './mapvote/mapvote-did-you-mean.js'; import mysqlLog from './mysql-log/index.js'; import seedingMessage from './seeding-message/index.js'; +import skipMap from './skipmap/index.js'; import teamRandomizer from './team-randomizer/index.js'; import chatCommands from './chat-commands/index.js'; - export { autoTKWarn, chatCommands, @@ -32,6 +32,7 @@ export { mapvoteDidYouMean, mysqlLog, seedingMessage, + skipMap, teamRandomizer }; @@ -51,6 +52,7 @@ const plugins = [ mapvoteDidYouMean, mysqlLog, seedingMessage, + skipMap, teamRandomizer ]; diff --git a/plugins/skipmap/index.js b/plugins/skipmap/index.js index 950fb71..2ce0302 100644 --- a/plugins/skipmap/index.js +++ b/plugins/skipmap/index.js @@ -1,4 +1,4 @@ -import { CHAT_MESSAGE } from 'squad-server/events'; +import { CHAT_MESSAGE, NEW_GAME } from 'squad-server/events'; export default { name: 'skipmap', @@ -13,6 +13,12 @@ export default { default: '!skipmap' }, + voteDuration: { + required: false, + description: 'How long the vote should go.', + default: 5 * 60 * 1000 + }, + startTimer: { required: false, description: 'Time to wait before allowing the vote to go through.', @@ -37,12 +43,6 @@ export default { default: 20 }, - reminderAmount: { - required: false, - description: 'The amount of reminders broadcasted.', - default: 5 - }, - reminderInterval: { required: false, description: 'The time between individual reminders.', @@ -50,25 +50,109 @@ export default { } }, - /* - TODO: - - Check Start Conditions - - Start Timer - - End Timer - - No previous vote failed within past X minutes, as set by options - - Check Vote End Conditions - - Enough Votes - - Voting - - Chat listener, add/subtract from counter - -> If counter positive in the end, skip map - - Broadcast reminders, as set by options - - - */ - init: async (server, options) => { + let votePos = 0; + let voteNeg = 0; + let intervalReminderBroadcasts; + let timeoutVote; + let timeLastVote; + let voteActive; + const playerVotes = {}; + server.on(CHAT_MESSAGE, (info) => { - if (info.message.chat.startsWith(options.command)) { + // Run through conditions + // check if message is command + if (!info.message.chat.startsWith(options.command)) return; + // check if enough time has passed since start of round and if not, inform the player + if (server.layerHistory[0].time < options.startTimer) { + const min = Math.floor( + ((options.startTimer - server.layerHistory[0].time) % (1000 * 60 * 60)) / (1000 * 60) + ); + const sec = Math.floor( + (options.startTimer - server.layerHistory[0].time) % ((1000 * 60) / 1000) + ); + server.rcon.warn( + info.steamID, + 'Not enough time has passed since the start of the match. Please try again in ' + + min + + 'm ' + + sec + + 's' + ); + return; } + // check if enough time remains in the round, if not, inform player + if (server.layerHistory[0].time < 2 * 60 * 60 * 1000 - options.endTimer) { + server.rcon.warn(info.steamID, 'Too close to expected end of match.'); + return; + } + + // check if enough time has passed since the last vote + if (timeLastVote - new Date() < options.pastVoteTimer) { + server.rcon.warn(info.steamID, 'Not enough time has passed since the last vote.'); + return; + } + + // Actual vote + voteActive = true; + votePos = 1; + playerVotes[info.steamID] = info.message; + voteNeg = 0; + // Set reminders + intervalReminderBroadcasts = setInterval(() => { + server.broadcast( + 'A vote to skip the current map has started. Please vote in favour with + or against with -.' + ); + server.broadcast('Current counter is: ' + votePos + ' in favour, ' + voteNeg + ' against.'); + }, options.reminderInterval); + + // End vote + // Disable recording of new votes, stop further broadcasts + timeoutVote = setTimeout(() => { + voteActive = false; + clearInterval(intervalReminderBroadcasts); + // Check if enough people voted + if (voteNeg + votePos < options.minVoteCount) { + server.rcon.broadcast('Not enough people voted for the vote to go through.'); + return; + } + if (votePos > voteNeg) { + server.rcon.execute('AdminEndMatch'); + } else { + server.rcon.broadcast( + 'Not enough people voted in favour of skipping the match. ' + + votePos + + ' voted in favour, ' + + voteNeg + + 'against.' + ); + } + }, options.voteDuration); + + // As a vote happened, stop any further votes from happening until enough time has passed + timeLastVote = new Date(); + }); + + // Clear timeouts and intervals when new game starts + server.on(NEW_GAME, (info) => { + clearInterval(intervalReminderBroadcasts); + clearTimeout(timeoutVote); + }); + + // Record votes + server.on(CHAT_MESSAGE, (info) => { + if (!voteActive) return; + + // Check if player has voted previously, if yes, remove their vote + if (playerVotes[info.steamID]) { + if (playerVotes[info.steamID] === '+') votePos--; + else voteNeg--; + } + + // Record player vote + if (info.message.startsWith('+')) votePos++; + else if (info.message.startsWith('-')) voteNeg--; + playerVotes[info.steamID] = info.message; }); } };