diff --git a/README.md b/README.md index e1b720e..b137e4f 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ Interested in creating your own plugin? [See more here](./squad-server/plugins/r
Description

Message SquadJS will send to players warning them they will be kicked

Default
-
Join a squad, you are are unassigned and will be kicked
+
Join a squad, you are unassigned and will be kicked
  • kickMessage

    Description

    Message to send to players when they are kicked

    diff --git a/config.json b/config.json index e68f5e5..c3e82bc 100644 --- a/config.json +++ b/config.json @@ -43,7 +43,7 @@ { "plugin": "AutoKickUnassigned", "enabled": true, - "warningMessage": "Join a squad, you are are unassigned and will be kicked", + "warningMessage": "Join a squad, you are unassigned and will be kicked", "kickMessage": "Unassigned - automatically removed", "frequencyOfWarnings": 30, "unassignedTimer": 360, diff --git a/core/logger.js b/core/logger.js index b20ddbe..564cf20 100644 --- a/core/logger.js +++ b/core/logger.js @@ -4,6 +4,7 @@ class Logger { constructor() { this.verboseness = {}; this.colors = {}; + this.includeTimestamps = false; } verbose(module, verboseness, message, ...extras) { @@ -11,7 +12,12 @@ class Logger { if (typeof colorFunc !== 'function') colorFunc = chalk.white; if ((this.verboseness[module] || 1) >= verboseness) - console.log(`[${colorFunc(module)}][${verboseness}] ${message}`, ...extras); + console.log( + `${this.includeTimestamps ? '[' + new Date().toISOString() + ']' : ''}[${colorFunc( + module + )}][${verboseness}] ${message}`, + ...extras + ); } setVerboseness(module, verboseness) { @@ -21,6 +27,10 @@ class Logger { setColor(module, color) { this.colors[module] = color; } + + setTimeStamps(option) { + this.includeTimestamps = option; + } } export default new Logger(); diff --git a/core/rcon.js b/core/rcon.js index af6b899..604cbf2 100644 --- a/core/rcon.js +++ b/core/rcon.js @@ -337,6 +337,8 @@ export default class Rcon extends EventEmitter { if (type === SERVERDATA_AUTH) { this.callbackIds.push({ id: this.count, cmd: body }); + Logger.verbose('RCON', 2, `Writing Auth Packet`); + Logger.verbose('RCON', 4, `Writing packet with type "${type}" and body "${body}".`); this.responseCallbackQueue.push(() => {}); this.responseCallbackQueue.push((decodedPacket) => { this.client.removeListener('error', onError); @@ -350,6 +352,7 @@ export default class Rcon extends EventEmitter { } }); } else { + Logger.verbose('RCON', 2, `Writing packet with type "${type}" and body "${body}".`); this.callbackIds.push({ id: this.count, cmd: body }); this.responseCallbackQueue.push((response) => { this.client.removeListener('error', onError); diff --git a/package.json b/package.json index f614ed0..29459d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "SquadJS", - "version": "3.6.1", + "version": "3.8.2", "repository": "https://github.com/Team-Silver-Sphere/SquadJS.git", "author": "Thomas Smyth ", "license": "BSL-1.0", diff --git a/squad-server/factory.js b/squad-server/factory.js index df91aa1..a8865a5 100644 --- a/squad-server/factory.js +++ b/squad-server/factory.js @@ -17,6 +17,8 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); export default class SquadServerFactory { static async buildFromConfig(config) { + Logger.setTimeStamps(config.logger.timestamps ? config.logger.timestamps : false); + const plugins = await Plugins.getPlugins(); for (const plugin of Object.keys(plugins)) { diff --git a/squad-server/index.js b/squad-server/index.js index 5aa1bf5..490f0a7 100644 --- a/squad-server/index.js +++ b/squad-server/index.js @@ -242,6 +242,8 @@ export default class SquadServer extends EventEmitter { this.logParser.on('PLAYER_WOUNDED', async (data) => { data.victim = await this.getPlayerByName(data.victimName); data.attacker = await this.getPlayerByName(data.attackerName); + if (!data.attacker) + data.attacker = await this.getPlayerByController(data.attackerPlayerController); if (data.victim && data.attacker) data.teamkill = @@ -257,6 +259,9 @@ export default class SquadServer extends EventEmitter { this.logParser.on('PLAYER_DIED', async (data) => { data.victim = await this.getPlayerByName(data.victimName); + data.attacker = await this.getPlayerByName(data.attackerName); + if (!data.attacker) + data.attacker = await this.getPlayerByController(data.attackerPlayerController); if (data.victim && data.attacker) data.teamkill = @@ -351,6 +356,9 @@ export default class SquadServer extends EventEmitter { players.push({ ...oldPlayerInfo[player.steamID], ...player, + playercontroller: this.logParser.eventStore.players[player.steamID] + ? this.logParser.eventStore.players[player.steamID].controller + : null, squad: await this.getSquadByID(player.teamID, player.squadID) }); @@ -542,6 +550,13 @@ export default class SquadServer extends EventEmitter { return this.getPlayerByCondition((player) => player.suffix === suffix, forceUpdate, false); } + async getPlayerByController(controller, forceUpdate) { + return this.getPlayerByCondition( + (player) => player.playercontroller === controller, + forceUpdate + ); + } + async pingSquadJSAPI() { if (this.pingSquadJSAPITimeout) clearTimeout(this.pingSquadJSAPITimeout); diff --git a/squad-server/layers/layer.js b/squad-server/layers/layer.js index e19fd30..78bb0b0 100644 --- a/squad-server/layers/layer.js +++ b/squad-server/layers/layer.js @@ -31,7 +31,7 @@ export default class Layer { respawnDelay: vehicle.respawnTime })), numberOfTanks: (data[t].vehicles || []).filter((v) => { - return v.icon.match(/tank/); + return v.icon.match(/_tank/); }).length, numberOfHelicopters: (data[t].vehicles || []).filter((v) => { return v.icon.match(/helo/); diff --git a/squad-server/layers/layers.js b/squad-server/layers/layers.js index 7020741..b2cc4da 100644 --- a/squad-server/layers/layers.js +++ b/squad-server/layers/layers.js @@ -22,7 +22,7 @@ class Layers { Logger.verbose('Layers', 1, 'Pulling layers...'); const response = await axios.get( - 'https://raw.githubusercontent.com/Squad-Wiki-Editorial/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) { diff --git a/squad-server/log-parser/player-disconnected.js b/squad-server/log-parser/player-disconnected.js index 6df5e64..352a012 100644 --- a/squad-server/log-parser/player-disconnected.js +++ b/squad-server/log-parser/player-disconnected.js @@ -1,6 +1,6 @@ export default { regex: - /^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: UNetConnection::Close: \[UNetConnection\] RemoteAddr: ([0-9]{17}):[0-9]+, Name: SteamNetConnection_[0-9]+, Driver: GameNetDriver SteamNetDriver_[0-9]+, IsServer: YES, PC: (BP_PlayerController_C_[0-9]+), Owner: BP_PlayerController_C_[0-9]+, UniqueId: Steam:UNKNOWN \[.*\], Channels: [0-9]+, Time: [0-9.:-]+/, + /^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: UChannel::Close: Sending CloseBunch\. ChIndex == [0-9]+\. Name: \[UChannel\] ChIndex: [0-9]+, Closing: [0-9]+ \[UNetConnection\] RemoteAddr: ([0-9]{17}):[0-9]+, Name: SteamNetConnection_[0-9]+, Driver: GameNetDriver SteamNetDriver_[0-9]+, IsServer: YES, PC: ([^ ]+PlayerController_C_[0-9]+), Owner: [^ ]+PlayerController_C_[0-9]+/, onMatch: (args, logParser) => { const data = { raw: args[0], diff --git a/squad-server/log-parser/player-possess.js b/squad-server/log-parser/player-possess.js index 68dda70..12ceb84 100644 --- a/squad-server/log-parser/player-possess.js +++ b/squad-server/log-parser/player-possess.js @@ -7,7 +7,8 @@ export default { time: args[1], chainID: args[2], playerSuffix: args[3], - possessClassname: args[4] + possessClassname: args[4], + pawn: args[5] }; logParser.eventStore.session[args[3]] = args[2]; diff --git a/squad-server/package.json b/squad-server/package.json index 8e63448..c7d8104 100644 --- a/squad-server/package.json +++ b/squad-server/package.json @@ -15,9 +15,9 @@ "pg": "^8.5.1", "pg-hstore": "^2.3.3", "sequelize": "^6.3.5", - "socket.io": "^3.1.2", + "socket.io": "^4.5.4", "sqlite3": "^5.0.0", - "tedious": "^9.2.1", + "tedious": "^15.1.2", "tinygradient": "^1.1.2" }, "exports": { diff --git a/squad-server/plugins/auto-kick-unassigned.js b/squad-server/plugins/auto-kick-unassigned.js index 8a8d784..1a4c81b 100644 --- a/squad-server/plugins/auto-kick-unassigned.js +++ b/squad-server/plugins/auto-kick-unassigned.js @@ -17,7 +17,7 @@ export default class AutoKickUnassigned extends BasePlugin { warningMessage: { required: false, description: 'Message SquadJS will send to players warning them they will be kicked', - default: 'Join a squad, you are are unassigned and will be kicked' + default: 'Join a squad, you are unassigned and will be kicked' }, kickMessage: { required: false, diff --git a/squad-server/plugins/discord-base-plugin.js b/squad-server/plugins/discord-base-plugin.js index 46e5ad1..26557ed 100644 --- a/squad-server/plugins/discord-base-plugin.js +++ b/squad-server/plugins/discord-base-plugin.js @@ -15,10 +15,24 @@ export default class DiscordBasePlugin extends BasePlugin { } async prepareToMount() { - this.channel = await this.options.discordClient.channels.fetch(this.options.channelID); + try { + this.channel = await this.options.discordClient.channels.fetch(this.options.channelID); + } catch (error) { + this.channel = null; + this.verbose( + 1, + `Could not fetch Discord channel with channelID "${this.options.channelID}". Error: ${error.message}` + ); + this.verbose(2, `${error.stack}`); + } } async sendDiscordMessage(message) { + if (!this.channel) { + this.verbose(1, `Could not send Discord Message. Channel not initialized.`); + return; + } + if (typeof message === 'object' && 'embed' in message) message.embed.footer = message.embed.footer || { text: COPYRIGHT_MESSAGE }; diff --git a/squad-server/rcon.js b/squad-server/rcon.js index 8c605b8..7209d7a 100644 --- a/squad-server/rcon.js +++ b/squad-server/rcon.js @@ -139,9 +139,11 @@ export default class SquadRcon extends Rcon { const players = []; + if (!response || response.length < 1) return players; + for (const line of response.split('\n')) { const match = line.match( - /ID: ([0-9]+) \| SteamID: ([0-9]{17}) \| Name: (.+) \| Team ID: ([0-9]+) \| Squad ID: ([0-9]+|N\/A)/ + /ID: ([0-9]+) \| SteamID: ([0-9]{17}) \| Name: (.+) \| Team ID: ([0-9]+) \| Squad ID: ([0-9]+|N\/A) \| Is Leader: (True|False) \| Role: ([A-Za-z0-9_]*)\b/ ); if (!match) continue; @@ -150,7 +152,9 @@ export default class SquadRcon extends Rcon { steamID: match[2], name: match[3], teamID: match[4], - squadID: match[5] !== 'N/A' ? match[5] : null + squadID: match[5] !== 'N/A' ? match[5] : null, + isLeader: match[6] === 'True', + role: match[7] }); } @@ -164,9 +168,11 @@ export default class SquadRcon extends Rcon { let teamName; let teamID; + if (!responseSquad || responseSquad.length < 1) return squads; + for (const line of responseSquad.split('\n')) { const match = line.match( - /ID: ([0-9]+) \| Name: (.+) \| Size: ([0-9]+) \| Locked: (True|False)/ + /ID: ([0-9]+) \| Name: (.+) \| Size: ([0-9]+) \| Locked: (True|False) \| Creator Name: (.+) \| Creator Steam ID: ([0-9]{17})/ ); const matchSide = line.match(/Team ID: (1|2) \((.+)\)/); if (matchSide) { @@ -174,11 +180,13 @@ export default class SquadRcon extends Rcon { teamName = matchSide[2]; } if (!match) continue; - await squads.push({ + squads.push({ squadID: match[1], squadName: match[2], size: match[3], locked: match[4], + creatorName: match[5], + creatorSteamID: match[6], teamID: teamID, teamName: teamName });