mirror of
https://github.com/AsgardEternal/SquadJS.git
synced 2024-09-28 17:34:25 -05:00
Merge pull request #318 from fantinodavide/eos-integration
EOS integration, major rewrite.
This commit is contained in:
commit
dffc8b6119
@ -16,9 +16,13 @@ export default class LogParser extends EventEmitter {
|
||||
|
||||
this.eventStore = {
|
||||
disconnected: {}, // holding area, cleared on map change.
|
||||
players: {}, // persistent data, steamid, controller, suffix.
|
||||
players: [], // persistent data, steamid, controller, suffix.
|
||||
playersEOS: [], // proxies from EOSID to persistent data, steamid, controller, suffix.
|
||||
connectionIdToSteamID: new Map(),
|
||||
session: {}, // old eventstore, nonpersistent data
|
||||
clients: {} // used in the connection chain before we resolve a player.
|
||||
clients: {}, // used in the connection chain before we resolve a player.
|
||||
lastConnection: {}, // used to store the last client connection data to then associate a steamid
|
||||
joinRequests: []
|
||||
};
|
||||
|
||||
this.linesPerMinute = 0;
|
||||
|
@ -337,8 +337,7 @@ 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);
|
||||
@ -352,7 +351,6 @@ 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);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "SquadJS",
|
||||
"version": "3.8.2",
|
||||
"version": "4.0.0",
|
||||
"repository": "https://github.com/Team-Silver-Sphere/SquadJS.git",
|
||||
"author": "Thomas Smyth <https://github.com/Thomas-Smyth>",
|
||||
"license": "BSL-1.0",
|
||||
|
@ -1,7 +1,6 @@
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import axios from 'axios';
|
||||
import Gamedig from 'gamedig';
|
||||
|
||||
import Logger from 'core/logger';
|
||||
import { SQUADJS_API_DOMAIN } from 'core/constants';
|
||||
@ -19,7 +18,7 @@ export default class SquadServer extends EventEmitter {
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
for (const option of ['host', 'queryPort'])
|
||||
for (const option of ['host'])
|
||||
if (!(option in options)) throw new Error(`${option} must be specified.`);
|
||||
|
||||
this.id = options.id;
|
||||
@ -73,13 +72,13 @@ export default class SquadServer extends EventEmitter {
|
||||
this.admins = await fetchAdminLists(this.options.adminLists);
|
||||
|
||||
await this.rcon.connect();
|
||||
await this.logParser.watch();
|
||||
|
||||
await this.updateSquadList();
|
||||
await this.updatePlayerList();
|
||||
await this.updatePlayerList(this);
|
||||
await this.updateLayerInformation();
|
||||
await this.updateA2SInformation();
|
||||
|
||||
await this.logParser.watch();
|
||||
|
||||
Logger.verbose('SquadServer', 1, `Watching ${this.serverName}...`);
|
||||
|
||||
await this.pingSquadJSAPI();
|
||||
@ -154,9 +153,12 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
|
||||
this.rcon.on('SQUAD_CREATED', async (data) => {
|
||||
data.player = await this.getPlayerBySteamID(data.playerSteamID, true);
|
||||
data.player = await this.getPlayerByEOSID(data.playerEOSID, true);
|
||||
data.player.squadID = data.squadID;
|
||||
|
||||
delete data.playerName;
|
||||
delete data.playerSteamID;
|
||||
delete data.playerEOSID;
|
||||
|
||||
this.emit('SQUAD_CREATED', data);
|
||||
});
|
||||
@ -207,7 +209,13 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
|
||||
this.logParser.on('PLAYER_CONNECTED', async (data) => {
|
||||
data.player = await this.getPlayerBySteamID(data.steamID);
|
||||
Logger.verbose(
|
||||
'SquadServer',
|
||||
1,
|
||||
`Player connected ${data.playerSuffix} - SteamID: ${data.steamID} - EOSID: ${data.eosID} - IP: ${data.ip}`
|
||||
);
|
||||
|
||||
data.player = await this.getPlayerByEOSID(data.eosID);
|
||||
if (data.player) data.player.suffix = data.playerSuffix;
|
||||
|
||||
delete data.steamID;
|
||||
@ -217,7 +225,7 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
|
||||
this.logParser.on('PLAYER_DISCONNECTED', async (data) => {
|
||||
data.player = await this.getPlayerBySteamID(data.steamID);
|
||||
data.player = await this.getPlayerByEOSID(data.eosID);
|
||||
|
||||
delete data.steamID;
|
||||
|
||||
@ -226,12 +234,16 @@ export default class SquadServer extends EventEmitter {
|
||||
|
||||
this.logParser.on('PLAYER_DAMAGED', async (data) => {
|
||||
data.victim = await this.getPlayerByName(data.victimName);
|
||||
data.attacker = await this.getPlayerByName(data.attackerName);
|
||||
data.attacker = await this.getPlayerByEOSID(data.attackerEOSID);
|
||||
|
||||
if (data.victim && data.attacker)
|
||||
if (data.attacker && !data.attacker.playercontroller && data.attackerController)
|
||||
data.attacker.playercontroller = data.attackerController;
|
||||
|
||||
if (data.victim && data.attacker) {
|
||||
data.teamkill =
|
||||
data.victim.teamID === data.attacker.teamID &&
|
||||
data.victim.steamID !== data.attacker.steamID;
|
||||
}
|
||||
|
||||
delete data.victimName;
|
||||
delete data.attackerName;
|
||||
@ -241,7 +253,7 @@ 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);
|
||||
data.attacker = await this.getPlayerByEOSID(data.attackerEOSID);
|
||||
if (!data.attacker)
|
||||
data.attacker = await this.getPlayerByController(data.attackerPlayerController);
|
||||
|
||||
@ -259,7 +271,7 @@ 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);
|
||||
data.attacker = await this.getPlayerByEOSID(data.attackerEOSID);
|
||||
if (!data.attacker)
|
||||
data.attacker = await this.getPlayerByController(data.attackerPlayerController);
|
||||
|
||||
@ -275,9 +287,9 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
|
||||
this.logParser.on('PLAYER_REVIVED', async (data) => {
|
||||
data.victim = await this.getPlayerByName(data.victimName);
|
||||
data.attacker = await this.getPlayerByName(data.attackerName);
|
||||
data.reviver = await this.getPlayerByName(data.reviverName);
|
||||
data.victim = await this.getPlayerByEOSID(data.victimEOSID);
|
||||
data.attacker = await this.getPlayerByEOSID(data.attackerEOSID);
|
||||
data.reviver = await this.getPlayerByEOSID(data.reviverEOSID);
|
||||
|
||||
delete data.victimName;
|
||||
delete data.attackerName;
|
||||
@ -287,7 +299,7 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
|
||||
this.logParser.on('PLAYER_POSSESS', async (data) => {
|
||||
data.player = await this.getPlayerByNameSuffix(data.playerSuffix);
|
||||
data.player = await this.getPlayerByEOSID(data.playerEOSID);
|
||||
if (data.player) data.player.possessClassname = data.possessClassname;
|
||||
|
||||
delete data.playerSuffix;
|
||||
@ -296,7 +308,7 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
|
||||
this.logParser.on('PLAYER_UNPOSSESS', async (data) => {
|
||||
data.player = await this.getPlayerByNameSuffix(data.playerSuffix);
|
||||
data.player = await this.getPlayerByEOSID(data.playerEOSID);
|
||||
|
||||
delete data.playerSuffix;
|
||||
|
||||
@ -310,6 +322,23 @@ export default class SquadServer extends EventEmitter {
|
||||
this.logParser.on('TICK_RATE', (data) => {
|
||||
this.emit('TICK_RATE', data);
|
||||
});
|
||||
|
||||
this.logParser.on('CLIENT_EXTERNAL_ACCOUNT_INFO', (data) => {
|
||||
this.rcon.addIds(data.steamID, data.eosID);
|
||||
});
|
||||
// this.logParser.on('CLIENT_CONNECTED', (data) => {
|
||||
// Logger.verbose("SquadServer", 1, `Client connected. Connection: ${data.connection} - SteamID: ${data.steamID}`)
|
||||
// })
|
||||
// this.logParser.on('CLIENT_LOGIN_REQUEST', (data) => {
|
||||
// Logger.verbose("SquadServer", 1, `Login request. ChainID: ${data.chainID} - Suffix: ${data.suffix} - EOSID: ${data.eosID}`)
|
||||
|
||||
// })
|
||||
// this.logParser.on('RESOLVED_EOS_ID', (data) => {
|
||||
// Logger.verbose("SquadServer", 1, `Resolved EOSID. ChainID: ${data.chainID} - Suffix: ${data.suffix} - EOSID: ${data.eosID}`)
|
||||
// })
|
||||
// this.logParser.on('ADDING_CLIENT_CONNECTION', (data) => {
|
||||
// Logger.verbose("SquadServer", 1, `Adding client connection`, data)
|
||||
// })
|
||||
}
|
||||
|
||||
async restartLogParser() {
|
||||
@ -352,7 +381,7 @@ export default class SquadServer extends EventEmitter {
|
||||
}
|
||||
|
||||
const players = [];
|
||||
for (const player of await this.rcon.getListPlayers())
|
||||
for (const player of await this.rcon.getListPlayers(this))
|
||||
players.push({
|
||||
...oldPlayerInfo[player.steamID],
|
||||
...player,
|
||||
@ -380,6 +409,13 @@ export default class SquadServer extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.a2sPlayerCount > 0 && players.length === 0)
|
||||
Logger.verbose(
|
||||
'SquadServer',
|
||||
1,
|
||||
`Real Player Count: ${this.a2sPlayerCount} but loaded ${players.length}`
|
||||
);
|
||||
|
||||
this.emit('UPDATED_PLAYER_INFORMATION');
|
||||
} catch (err) {
|
||||
Logger.verbose('SquadServer', 1, 'Failed to update player list.', err);
|
||||
@ -441,53 +477,70 @@ export default class SquadServer extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
async updateA2SInformation() {
|
||||
updateA2SInformation() {
|
||||
return this.updateServerInformation();
|
||||
}
|
||||
|
||||
async updateServerInformation() {
|
||||
if (this.updateA2SInformationTimeout) clearTimeout(this.updateA2SInformationTimeout);
|
||||
|
||||
Logger.verbose('SquadServer', 1, `Updating A2S information...`);
|
||||
Logger.verbose('SquadServer', 1, `Updating server information...`);
|
||||
|
||||
try {
|
||||
const data = await Gamedig.query({
|
||||
type: 'squad',
|
||||
host: this.options.host,
|
||||
port: this.options.queryPort
|
||||
});
|
||||
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);
|
||||
|
||||
const info = {
|
||||
raw: data.raw,
|
||||
serverName: data.name,
|
||||
raw: data,
|
||||
serverName: data.ServerName_s,
|
||||
|
||||
maxPlayers: parseInt(data.maxplayers),
|
||||
publicSlots: parseInt(data.raw.rules.NUMPUBCONN),
|
||||
reserveSlots: parseInt(data.raw.rules.NUMPRIVCONN),
|
||||
maxPlayers: parseInt(data.MaxPlayers),
|
||||
publicQueueLimit: parseInt(data.PublicQueueLimit_I),
|
||||
reserveSlots: parseInt(data.PlayerReserveCount_I),
|
||||
|
||||
a2sPlayerCount: parseInt(data.raw.rules.PlayerCount_i),
|
||||
publicQueue: parseInt(data.raw.rules.PublicQueue_i),
|
||||
reserveQueue: parseInt(data.raw.rules.ReservedQueue_i),
|
||||
playerCount: parseInt(data.PlayerCount_I),
|
||||
a2sPlayerCount: parseInt(data.PlayerCount_I),
|
||||
publicQueue: parseInt(data.PublicQueue_I),
|
||||
reserveQueue: parseInt(data.ReservedQueue_I),
|
||||
|
||||
matchTimeout: parseFloat(data.raw.rules.MatchTimeout_f),
|
||||
gameVersion: data.raw.version
|
||||
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'), '') || '',
|
||||
|
||||
matchTimeout: parseFloat(data.MatchTimeout_d),
|
||||
matchStartTime: this.getMatchStartTimeByPlaytime(data.PLAYTIME_I),
|
||||
gameVersion: data.GameVersion_s
|
||||
};
|
||||
|
||||
this.serverName = info.serverName;
|
||||
|
||||
this.maxPlayers = info.maxPlayers;
|
||||
this.publicSlots = info.publicSlots;
|
||||
this.publicSlots = info.maxPlayers - info.reserveSlots;
|
||||
this.reserveSlots = info.reserveSlots;
|
||||
|
||||
this.a2sPlayerCount = info.a2sPlayerCount;
|
||||
this.a2sPlayerCount = info.playerCount;
|
||||
this.playerCount = info.playerCount;
|
||||
this.publicQueue = info.publicQueue;
|
||||
this.reserveQueue = info.reserveQueue;
|
||||
|
||||
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);
|
||||
|
||||
this.emit('UPDATED_A2S_INFORMATION', info);
|
||||
this.emit('UPDATED_SERVER_INFORMATION', info);
|
||||
} catch (err) {
|
||||
Logger.verbose('SquadServer', 1, 'Failed to update A2S information.', err);
|
||||
Logger.verbose('SquadServer', 1, 'Failed to update server information.', err);
|
||||
}
|
||||
|
||||
Logger.verbose('SquadServer', 1, `Updated A2S information.`);
|
||||
Logger.verbose('SquadServer', 1, `Updated server information.`);
|
||||
|
||||
this.updateA2SInformationTimeout = setTimeout(
|
||||
this.updateA2SInformation,
|
||||
@ -542,6 +595,10 @@ export default class SquadServer extends EventEmitter {
|
||||
return this.getPlayerByCondition((player) => player.steamID === steamID, forceUpdate);
|
||||
}
|
||||
|
||||
async getPlayerByEOSID(eosID, forceUpdate) {
|
||||
return this.getPlayerByCondition((player) => player.eosID === eosID, forceUpdate);
|
||||
}
|
||||
|
||||
async getPlayerByName(name, forceUpdate) {
|
||||
return this.getPlayerByCondition((player) => player.name === name, forceUpdate);
|
||||
}
|
||||
@ -606,4 +663,8 @@ export default class SquadServer extends EventEmitter {
|
||||
|
||||
this.pingSquadJSAPITimeout = setTimeout(this.pingSquadJSAPI, this.pingSquadJSAPIInterval);
|
||||
}
|
||||
|
||||
getMatchStartTimeByPlaytime(playtime) {
|
||||
return new Date(Date.now() - +playtime * 1000);
|
||||
}
|
||||
}
|
||||
|
20
squad-server/log-parser/adding-client-connection.js
Normal file
20
squad-server/log-parser/adding-client-connection.js
Normal file
@ -0,0 +1,20 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: AddClientConnection: Added client connection: \[UNetConnection\] RemoteAddr: ([\d.]+):[0-9]+, Name: (EOSIpNetConnection_[0-9]+), Driver: GameNetDriver (EOSNetDriver_[0-9]+), IsServer: YES, PC: NULL, Owner: NULL, UniqueId: INVALID/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
// steamID: args[ 3 ],
|
||||
ip: args[3],
|
||||
connection: args[4],
|
||||
driver: args[5]
|
||||
};
|
||||
/* This is Called when unreal engine adds a client connection
|
||||
First Step in Adding a Player to server
|
||||
*/
|
||||
logParser.eventStore['last-connection'] = data;
|
||||
logParser.emit('ADDING_CLIENT_CONNECTION', data);
|
||||
}
|
||||
};
|
15
squad-server/log-parser/check-permission-resolve-eosid.js
Normal file
15
squad-server/log-parser/check-permission-resolve-eosid.js
Normal file
@ -0,0 +1,15 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadCommon: SQCommonStatics Check Permissions, UniqueId:([\da-f]+)$/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: +args[2],
|
||||
eosID: args[3]
|
||||
};
|
||||
|
||||
logParser.eventStore.joinRequests[data.chainID].eosID = data.eosID;
|
||||
logParser.emit('RESOLVED_EOS_ID', { ...logParser.eventStore.joinRequests[data.chainID] });
|
||||
}
|
||||
};
|
21
squad-server/log-parser/client-external-account-info.js
Normal file
21
squad-server/log-parser/client-external-account-info.js
Normal file
@ -0,0 +1,21 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]+)]LogEOS: Verbose: \[LogEOSConnect] FConnectClient::CacheExternalAccountInfo - ProductUserId: (?<eosId>[0-9a-f]{32}), AccountType: (\d), AccountId: (?<steamId>[0-9]{17}), DisplayName: <Redacted>/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
eosID: args.groups.eosId,
|
||||
steamID: args.groups.steamId
|
||||
};
|
||||
|
||||
logParser.eventStore.players[data.steamID] = {
|
||||
eosID: data.eosID,
|
||||
steamID: data.steamID
|
||||
};
|
||||
logParser.eventStore.playersEOS[data.eosID] = logParser.eventStore.players[data.steamID];
|
||||
|
||||
logParser.emit('CLIENT_EXTERNAL_ACCOUNT_INFO', data);
|
||||
}
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: Login: NewPlayer: SteamNetConnection \/Engine\/Transient\.(SteamNetConnection_[0-9]+)/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: Login: NewPlayer: EOSIpNetConnection \/Engine\/Transient\.(EOSIpNetConnection_[0-9]+)/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
@ -13,7 +13,7 @@ export default {
|
||||
2nd Step in player connected path
|
||||
*/
|
||||
|
||||
logParser.eventStore['client-login'] = logParser.eventStore.clients[args[3]];
|
||||
logParser.eventStore.joinRequests[data.chainID].connection = data.connection;
|
||||
delete logParser.eventStore.clients[args[3]];
|
||||
logParser.emit('CLIENT_LOGIN', data);
|
||||
}
|
||||
|
@ -16,10 +16,15 @@ import RoundEnded from './round-ended.js';
|
||||
import RoundTickets from './round-tickets.js';
|
||||
import RoundWinner from './round-winner.js';
|
||||
import ServerTickRate from './server-tick-rate.js';
|
||||
import ClientConnected from './client-connected.js';
|
||||
import AddingClientConnection from './adding-client-connection.js';
|
||||
import ClientLogin from './client-login.js';
|
||||
import PendingConnectionDestroyed from './pending-connection-destroyed.js';
|
||||
|
||||
import ClientExternalAccountInfo from './client-external-account-info.js';
|
||||
import SendingAuthResult from './sending-auth-result.js';
|
||||
import LoginRequest from './login-request.js';
|
||||
import JoinRequest from './join-request.js';
|
||||
import PlayerJoinSucceeded from './player-join-succeeded.js';
|
||||
import CheckPermissionResolveEosid from './check-permission-resolve-eosid.js';
|
||||
export default class SquadLogParser extends LogParser {
|
||||
constructor(options) {
|
||||
super('SquadGame.log', options);
|
||||
@ -43,9 +48,15 @@ export default class SquadLogParser extends LogParser {
|
||||
RoundTickets,
|
||||
RoundWinner,
|
||||
ServerTickRate,
|
||||
ClientConnected,
|
||||
AddingClientConnection,
|
||||
ClientLogin,
|
||||
PendingConnectionDestroyed
|
||||
PendingConnectionDestroyed,
|
||||
ClientExternalAccountInfo,
|
||||
SendingAuthResult,
|
||||
LoginRequest,
|
||||
JoinRequest,
|
||||
PlayerJoinSucceeded,
|
||||
CheckPermissionResolveEosid
|
||||
];
|
||||
}
|
||||
}
|
||||
|
15
squad-server/log-parser/join-request.js
Normal file
15
squad-server/log-parser/join-request.js
Normal file
@ -0,0 +1,15 @@
|
||||
export default {
|
||||
regex: /^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: Join request: .+\?Name=(.+)\?SplitscreenCount=\d$/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: +args[2],
|
||||
suffix: args[3]
|
||||
};
|
||||
|
||||
logParser.eventStore.joinRequests[data.chainID] = data;
|
||||
// console.log(logParser.eventStore.loginRequests[ data.chainID ])
|
||||
logParser.emit('CLIENT_JOIN_REQUEST', data);
|
||||
}
|
||||
};
|
17
squad-server/log-parser/login-request.js
Normal file
17
squad-server/log-parser/login-request.js
Normal file
@ -0,0 +1,17 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: Login request: \?Name=(.+?)(?:\?PASSWORD=(?:.+?))? userId: RedpointEOS:([\da-f]{32}) platform: RedpointEOS/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: +args[2],
|
||||
suffix: args[3],
|
||||
eosID: args[4]
|
||||
};
|
||||
|
||||
// logParser.eventStore.loginRequests[ data.chainID ] = data;
|
||||
// console.log(logParser.eventStore.loginRequests[ data.chainID ])
|
||||
logParser.emit('CLIENT_LOGIN_REQUEST', data);
|
||||
}
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: UNetConnection::PendingConnectionLost\. \[UNetConnection\] RemoteAddr: ([0-9]{17}):[0-9]+, Name: (SteamNetConnection_[0-9]+), Driver: GameNetDriver (SteamNetDriver_[0-9]+), IsServer: YES, PC: NULL, Owner: NULL, UniqueId: (?:Steam:UNKNOWN \[.+\]|INVALID) bPendingDestroy=0/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: UNetConnection::PendingConnectionLost\. \[UNetConnection\] RemoteAddr: ([0-9a-f]{32}):[0-9]+, Name: (SteamNetConnection_[0-9]+), Driver: GameNetDriver (SteamNetDriver_[0-9]+), IsServer: YES, PC: NULL, Owner: NULL, UniqueId: (?:Steam:UNKNOWN \[.+\]|INVALID) bPendingDestroy=0/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
|
@ -1,27 +1,25 @@
|
||||
export default {
|
||||
regex: /^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: Join succeeded: (.+)/,
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: PostLogin: NewPlayer: BP_PlayerController_C .+PersistentLevel\.([^\s]+) \(IP: ([\d.]+) \| Online IDs: EOS: ([0-9a-f]{32}) steam: (\d+)\)/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
playerSuffix: args[3],
|
||||
steamID: logParser.eventStore['client-login'], // player connected
|
||||
controller: logParser.eventStore['player-controller'] // playercontroller connected
|
||||
chainID: +args[2],
|
||||
playercontroller: args[3],
|
||||
ip: args[4],
|
||||
eosID: args[5],
|
||||
steamID: args[6]
|
||||
};
|
||||
|
||||
delete logParser.eventStore['client-login'];
|
||||
delete logParser.eventStore['player-controller'];
|
||||
const joinRequestData = logParser.eventStore.joinRequests[+args[2]];
|
||||
data.connection = joinRequestData.connection;
|
||||
data.playerSuffix = joinRequestData.suffix;
|
||||
|
||||
if (!logParser.eventStore.players[data.steamID])
|
||||
logParser.eventStore.players[data.steamID] = {};
|
||||
logParser.eventStore.players[data.steamID].controller = data.playercontroller;
|
||||
|
||||
// Handle Reconnecting players
|
||||
if (logParser.eventStore.disconnected[data.steamID]) {
|
||||
delete logParser.eventStore.disconnected[data.steamID];
|
||||
}
|
||||
logParser.emit('PLAYER_CONNECTED', data);
|
||||
logParser.eventStore.players[data.steamID] = {
|
||||
steamID: data.steamID,
|
||||
suffix: data.playerSuffix,
|
||||
controller: data.controller
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: Player:(.+) ActualDamage=([0-9.]+) from (.+) caused by ([A-z_0-9-]+)_C/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: Player:(.+) ActualDamage=([0-9.]+) from (.+) \(Online IDs: EOS: ([0-9a-f]{32}) steam: (\d{17}) \| Player Controller ID: ([^ ]+)\)caused by ([A-z_0-9-]+)_C/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
@ -9,11 +9,18 @@ export default {
|
||||
victimName: args[3],
|
||||
damage: parseFloat(args[4]),
|
||||
attackerName: args[5],
|
||||
weapon: args[6]
|
||||
attackerEOSID: args[6],
|
||||
attackerSteamID: args[7],
|
||||
attackerController: args[8],
|
||||
weapon: args[9]
|
||||
};
|
||||
|
||||
logParser.eventStore.session[args[3]] = data;
|
||||
|
||||
if (!logParser.eventStore.players[data.attackerSteamID])
|
||||
logParser.eventStore.players[data.attackerSteamID] = {};
|
||||
logParser.eventStore.players[data.attackerSteamID].controller = data.attackerController;
|
||||
|
||||
logParser.emit('PLAYER_DAMAGED', data);
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQSoldier::)?Die\(\): Player:(.+) KillingDamage=(?:-)*([0-9.]+) from ([A-z_0-9]+) caused by ([A-z_0-9-]+)_C/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQSoldier::)?Die\(\): Player:(.+) KillingDamage=(?:-)*([0-9.]+) from ([A-z_0-9]+) \(Online IDs: EOS: ([\w\d]{32}) steam: (\d{17}) \| Contoller ID: ([\w\d]+)\) caused by ([A-z_0-9-]+)_C/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
...logParser.eventStore.session[args[3]],
|
||||
@ -11,7 +11,9 @@ export default {
|
||||
victimName: args[3],
|
||||
damage: parseFloat(args[4]),
|
||||
attackerPlayerController: args[5],
|
||||
weapon: args[6]
|
||||
attackerEOSID: args[6],
|
||||
attackerSteamID: args[7],
|
||||
weapon: args[9]
|
||||
};
|
||||
|
||||
logParser.eventStore.session[args[3]] = data;
|
||||
|
@ -1,16 +1,18 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([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]+/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: UChannel::Close: Sending CloseBunch\. ChIndex == [0-9]+\. Name: \[UChannel\] ChIndex: [0-9]+, Closing: [0-9]+ \[UNetConnection\] RemoteAddr: ([\d.]+):[\d]+, Name: EOSIpNetConnection_[0-9]+, Driver: GameNetDriver EOSNetDriver_[0-9]+, IsServer: YES, PC: ([^ ]+PlayerController_C_[0-9]+), Owner: [^ ]+PlayerController_C_[0-9]+, UniqueId: RedpointEOS:([\d\w]+)/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
steamID: args[3],
|
||||
playerController: args[4]
|
||||
ip: args[3],
|
||||
playerController: args[4],
|
||||
eosID: args[5]
|
||||
};
|
||||
|
||||
logParser.eventStore.disconnected[data.steamID] = true;
|
||||
|
||||
logParser.emit('PLAYER_DISCONNECTED', data);
|
||||
}
|
||||
};
|
||||
|
28
squad-server/log-parser/player-join-succeeded.js
Normal file
28
squad-server/log-parser/player-join-succeeded.js
Normal file
@ -0,0 +1,28 @@
|
||||
export default {
|
||||
regex: /^\[([0-9.:-]+)]\[([ 0-9]*)]LogNet: Join succeeded: (.+)/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: +args[2],
|
||||
playerSuffix: args[3]
|
||||
};
|
||||
|
||||
const joinRequestsData = { ...logParser.eventStore.joinRequests[data.chainID] };
|
||||
|
||||
data.eosID = joinRequestsData.eosID;
|
||||
data.controller = joinRequestsData.controller;
|
||||
data.steamID = `${logParser.eventStore.connectionIdToSteamID.get(joinRequestsData.connection)}`;
|
||||
|
||||
logParser.eventStore.connectionIdToSteamID.delete(joinRequestsData.connection);
|
||||
|
||||
delete logParser.eventStore.joinRequests[+data.chainID];
|
||||
|
||||
// Handle Reconnecting players
|
||||
if (logParser.eventStore.disconnected[data.steamID]) {
|
||||
delete logParser.eventStore.disconnected[data.steamID];
|
||||
}
|
||||
|
||||
logParser.emit('JOIN_SUCCEEDED', data);
|
||||
}
|
||||
};
|
@ -1,13 +1,15 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQPlayerController::)?OnPossess\(\): PC=(.+) Pawn=([A-z0-9_]+)_C/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQPlayerController::)?OnPossess\(\): PC=(.+) \(Online IDs: EOS: ([\w\d]{32}) steam: (\d{17})\) Pawn=([A-z0-9_]+)_C/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
playerSuffix: args[3],
|
||||
possessClassname: args[4],
|
||||
playerEOSID: args[4],
|
||||
playerSteamID: args[5],
|
||||
possessClassname: args[6],
|
||||
pawn: args[5]
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
export default {
|
||||
// the names are currently the wrong way around in these logs
|
||||
regex: /^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: (.+) has revived (.+)\./,
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquad: (.+) \(Online IDs: EOS: ([0-9a-f]{32}) steam: (\d{17})\) has revived (.+) \(Online IDs: EOS: ([0-9a-f]{32}) steam: (\d{17})\)\./,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
...logParser.eventStore.session[args[3]],
|
||||
@ -8,7 +9,11 @@ export default {
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
reviverName: args[3],
|
||||
victimName: args[4]
|
||||
reviverEOSID: args[4],
|
||||
reviverSteamID: args[5],
|
||||
victimName: args[6],
|
||||
victimEOSID: args[7],
|
||||
victimSteamID: args[8]
|
||||
};
|
||||
|
||||
logParser.emit('PLAYER_REVIVED', data);
|
||||
|
@ -1,14 +1,16 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQPlayerController::)?OnUnPossess\(\): PC=(.+)/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQPlayerController::)?OnUnPossess\(\): PC=(.+) \(Online IDs: EOS: ([\w\d]{32}) steam: (\d{17})\)/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
playerSuffix: args[3],
|
||||
playerEOSID: args[4],
|
||||
playerSteamID: args[5],
|
||||
switchPossess:
|
||||
args[3] in logParser.eventStore.session && logParser.eventStore.session[args[3]] === args[2]
|
||||
args[4] in logParser.eventStore.session && logParser.eventStore.session[args[4]] === args[2]
|
||||
};
|
||||
|
||||
delete logParser.eventStore.session[args[3]];
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQSoldier::)?Wound\(\): Player:(.+) KillingDamage=(?:-)*([0-9.]+) from ([A-z_0-9]+) caused by ([A-z_0-9-]+)_C/,
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogSquadTrace: \[DedicatedServer](?:ASQSoldier::)?Wound\(\): Player:(.+) KillingDamage=(?:-)*([0-9.]+) from ([A-z_0-9]+) \(Online IDs: EOS: ([\w\d]{32}) steam: (\d{17}) \| Controller ID: ([\w\d]+)\) caused by ([A-z_0-9-]+)_C/,
|
||||
onMatch: (args, logParser) => {
|
||||
const data = {
|
||||
...logParser.eventStore.session[args[3]],
|
||||
@ -10,7 +10,9 @@ export default {
|
||||
victimName: args[3],
|
||||
damage: parseFloat(args[4]),
|
||||
attackerPlayerController: args[5],
|
||||
weapon: args[6]
|
||||
attackerEOSID: args[6],
|
||||
attackerSteamID: args[7],
|
||||
weapon: args[9]
|
||||
};
|
||||
|
||||
logParser.eventStore.session[args[3]] = data;
|
||||
|
@ -5,12 +5,11 @@ export default {
|
||||
const data = {
|
||||
raw: args[0],
|
||||
time: args[1],
|
||||
chainID: args[2],
|
||||
chainID: +args[2],
|
||||
controller: args[3]
|
||||
};
|
||||
|
||||
logParser.eventStore['player-controller'] = args[3];
|
||||
|
||||
logParser.eventStore.joinRequests[data.chainID].controller = data.controller;
|
||||
logParser.emit('PLAYER_CONTROLLER_CONNECTED', data);
|
||||
}
|
||||
};
|
||||
|
21
squad-server/log-parser/sending-auth-result.js
Normal file
21
squad-server/log-parser/sending-auth-result.js
Normal file
@ -0,0 +1,21 @@
|
||||
export default {
|
||||
regex:
|
||||
/^\[([0-9.:-]+)]\[([ 0-9]*)]LogOnline: STEAM: AUTH HANDLER: Sending auth result to user (\d{17}) with flag success\? 1/,
|
||||
onMatch: (args, logParser) => {
|
||||
if (!logParser.eventStore['last-connection']) return;
|
||||
|
||||
const data = {
|
||||
...logParser.eventStore['last-connection'],
|
||||
steamID: args[3]
|
||||
};
|
||||
/* This is Called when unreal engine adds a client connection
|
||||
First Step in Adding a Player to server
|
||||
*/
|
||||
|
||||
logParser.eventStore.clients[data.connection] = data.steamID;
|
||||
logParser.eventStore.connectionIdToSteamID.set(data.connection, data.steamID);
|
||||
logParser.emit('CLIENT_CONNECTED', data);
|
||||
|
||||
delete logParser.eventStore['last-connection'];
|
||||
}
|
||||
};
|
@ -2,7 +2,7 @@ import Sequelize from 'sequelize';
|
||||
|
||||
import BasePlugin from './base-plugin.js';
|
||||
|
||||
const { DataTypes } = Sequelize;
|
||||
const { DataTypes, QueryTypes } = Sequelize;
|
||||
|
||||
export default class DBLog extends BasePlugin {
|
||||
static get description() {
|
||||
@ -146,6 +146,44 @@ export default class DBLog extends BasePlugin {
|
||||
}
|
||||
);
|
||||
|
||||
this.createModel(
|
||||
'Player',
|
||||
{
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
eosID: {
|
||||
type: DataTypes.STRING,
|
||||
unique: true
|
||||
},
|
||||
steamID: {
|
||||
type: DataTypes.STRING,
|
||||
notNull: true,
|
||||
unique: true
|
||||
},
|
||||
lastName: {
|
||||
type: DataTypes.STRING
|
||||
},
|
||||
lastIP: {
|
||||
type: DataTypes.STRING
|
||||
}
|
||||
},
|
||||
{
|
||||
charset: 'utf8mb4',
|
||||
collate: 'utf8mb4_unicode_ci',
|
||||
indexes: [
|
||||
{
|
||||
fields: ['eosID']
|
||||
},
|
||||
{
|
||||
fields: ['steamID']
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
this.createModel(
|
||||
'Wound',
|
||||
{
|
||||
@ -329,37 +367,44 @@ export default class DBLog extends BasePlugin {
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Wound, {
|
||||
this.models.Player.hasMany(this.models.Wound, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'attacker' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Wound, {
|
||||
this.models.Player.hasMany(this.models.Wound, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'victim' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Death, {
|
||||
this.models.Player.hasMany(this.models.Death, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'attacker' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Death, {
|
||||
this.models.Player.hasMany(this.models.Death, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'victim' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Revive, {
|
||||
this.models.Player.hasMany(this.models.Revive, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'attacker' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Revive, {
|
||||
this.models.Player.hasMany(this.models.Revive, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'victim' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.models.SteamUser.hasMany(this.models.Revive, {
|
||||
this.models.Player.hasMany(this.models.Revive, {
|
||||
sourceKey: 'steamID',
|
||||
foreignKey: { name: 'reviver' },
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
@ -392,9 +437,12 @@ export default class DBLog extends BasePlugin {
|
||||
this.onTickRate = this.onTickRate.bind(this);
|
||||
this.onUpdatedA2SInformation = this.onUpdatedA2SInformation.bind(this);
|
||||
this.onNewGame = this.onNewGame.bind(this);
|
||||
this.onPlayerConnected = this.onPlayerConnected.bind(this);
|
||||
this.onPlayerWounded = this.onPlayerWounded.bind(this);
|
||||
this.onPlayerDied = this.onPlayerDied.bind(this);
|
||||
this.onPlayerRevived = this.onPlayerRevived.bind(this);
|
||||
this.migrateSteamUsersIntoPlayers = this.migrateSteamUsersIntoPlayers.bind(this);
|
||||
this.dropAllForeignKeys = this.dropAllForeignKeys.bind(this);
|
||||
}
|
||||
|
||||
createModel(name, schema) {
|
||||
@ -409,12 +457,15 @@ export default class DBLog extends BasePlugin {
|
||||
await this.models.TickRate.sync();
|
||||
await this.models.PlayerCount.sync();
|
||||
await this.models.SteamUser.sync();
|
||||
await this.models.Player.sync();
|
||||
await this.models.Wound.sync();
|
||||
await this.models.Death.sync();
|
||||
await this.models.Revive.sync();
|
||||
}
|
||||
|
||||
async mount() {
|
||||
await this.migrateSteamUsersIntoPlayers();
|
||||
|
||||
await this.models.Server.upsert({
|
||||
id: this.options.overrideServerID || this.server.id,
|
||||
name: this.server.serverName
|
||||
@ -427,6 +478,7 @@ export default class DBLog extends BasePlugin {
|
||||
this.server.on('TICK_RATE', this.onTickRate);
|
||||
this.server.on('UPDATED_A2S_INFORMATION', this.onUpdatedA2SInformation);
|
||||
this.server.on('NEW_GAME', this.onNewGame);
|
||||
this.server.on('PLAYER_CONNECTED', this.onPlayerConnected);
|
||||
this.server.on('PLAYER_WOUNDED', this.onPlayerWounded);
|
||||
this.server.on('PLAYER_DIED', this.onPlayerDied);
|
||||
this.server.on('PLAYER_REVIVED', this.onPlayerRevived);
|
||||
@ -436,6 +488,7 @@ export default class DBLog extends BasePlugin {
|
||||
this.server.removeEventListener('TICK_RATE', this.onTickRate);
|
||||
this.server.removeEventListener('UPDATED_A2S_INFORMATION', this.onTickRate);
|
||||
this.server.removeEventListener('NEW_GAME', this.onNewGame);
|
||||
this.server.removeEventListener('PLAYER_CONNECTED', this.onPlayerConnected);
|
||||
this.server.removeEventListener('PLAYER_WOUNDED', this.onPlayerWounded);
|
||||
this.server.removeEventListener('PLAYER_DIED', this.onPlayerDied);
|
||||
this.server.removeEventListener('PLAYER_REVIVED', this.onPlayerRevived);
|
||||
@ -479,15 +532,27 @@ export default class DBLog extends BasePlugin {
|
||||
|
||||
async onPlayerWounded(info) {
|
||||
if (info.attacker)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.attacker.steamID,
|
||||
lastName: info.attacker.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.attacker.eosID,
|
||||
steamID: info.attacker.steamID,
|
||||
lastName: info.attacker.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
if (info.victim)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.victim.steamID,
|
||||
lastName: info.victim.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.victim.eosID,
|
||||
steamID: info.victim.steamID,
|
||||
lastName: info.victim.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
|
||||
await this.models.Wound.create({
|
||||
server: this.options.overrideServerID || this.server.id,
|
||||
@ -509,15 +574,27 @@ export default class DBLog extends BasePlugin {
|
||||
|
||||
async onPlayerDied(info) {
|
||||
if (info.attacker)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.attacker.steamID,
|
||||
lastName: info.attacker.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.attacker.eosID,
|
||||
steamID: info.attacker.steamID,
|
||||
lastName: info.attacker.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
if (info.victim)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.victim.steamID,
|
||||
lastName: info.victim.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.victim.eosID,
|
||||
steamID: info.victim.steamID,
|
||||
lastName: info.victim.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
|
||||
await this.models.Death.create({
|
||||
server: this.options.overrideServerID || this.server.id,
|
||||
@ -540,20 +617,38 @@ export default class DBLog extends BasePlugin {
|
||||
|
||||
async onPlayerRevived(info) {
|
||||
if (info.attacker)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.attacker.steamID,
|
||||
lastName: info.attacker.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.attacker.eosID,
|
||||
steamID: info.attacker.steamID,
|
||||
lastName: info.attacker.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
if (info.victim)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.victim.steamID,
|
||||
lastName: info.victim.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.victim.eosID,
|
||||
steamID: info.victim.steamID,
|
||||
lastName: info.victim.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
if (info.reviver)
|
||||
await this.models.SteamUser.upsert({
|
||||
steamID: info.reviver.steamID,
|
||||
lastName: info.reviver.name
|
||||
});
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.reviver.eosID,
|
||||
steamID: info.reviver.steamID,
|
||||
lastName: info.reviver.name
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
|
||||
await this.models.Revive.create({
|
||||
server: this.options.overrideServerID || this.server.id,
|
||||
@ -577,4 +672,89 @@ export default class DBLog extends BasePlugin {
|
||||
reviverSquadID: info.reviver ? info.reviver.squadID : null
|
||||
});
|
||||
}
|
||||
|
||||
async onPlayerConnected(info) {
|
||||
await this.models.Player.upsert(
|
||||
{
|
||||
eosID: info.eosID,
|
||||
steamID: info.player.steamID,
|
||||
lastName: info.player.name,
|
||||
lastIP: info.ip
|
||||
},
|
||||
{
|
||||
conflictFields: ['steamID']
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async migrateSteamUsersIntoPlayers() {
|
||||
try {
|
||||
const steamUsersCount = await this.models.SteamUser.count();
|
||||
const playersCount = await this.models.Player.count();
|
||||
|
||||
if (steamUsersCount < playersCount) {
|
||||
this.verbose(
|
||||
1,
|
||||
`Skipping migration from SteamUsers to Players due to a previous successful migration.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await this.dropAllForeignKeys();
|
||||
|
||||
const steamUsers = (await this.models.SteamUser.findAll()).map((u) => u.dataValues);
|
||||
await this.models.Player.bulkCreate(steamUsers);
|
||||
|
||||
this.verbose(1, `Migration from SteamUsers to Players successful`);
|
||||
} catch (error) {
|
||||
this.verbose(1, `Error during Migration from SteamUsers to Players: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
async dropAllForeignKeys() {
|
||||
this.verbose(
|
||||
1,
|
||||
`Starting to drop constraints on DB: ${this.options.database.config.database} related to DBLog_SteamUsers deptecated table.`
|
||||
);
|
||||
for (const modelName in this.models) {
|
||||
const model = this.models[modelName];
|
||||
const tableName = model.tableName;
|
||||
|
||||
try {
|
||||
const result = await this.options.database.query(
|
||||
`SELECT * FROM information_schema.key_column_usage WHERE referenced_table_name IS NOT NULL AND table_schema = '${this.options.database.config.database}' AND table_name = '${tableName}';`,
|
||||
{ type: QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
for (const r of result) {
|
||||
if (r.REFERENCED_TABLE_NAME === 'DBLog_SteamUsers') {
|
||||
this.verbose(
|
||||
1,
|
||||
`Found constraint ${r.COLUMN_NAME} on table ${tableName}, referencing ${r.REFERENCED_COLUMN_NAME} on ${r.REFERENCED_TABLE_NAME}`
|
||||
);
|
||||
|
||||
await this.options.database
|
||||
.query(`ALTER TABLE ${tableName} DROP FOREIGN KEY ${r.CONSTRAINT_NAME}`, {
|
||||
type: QueryTypes.RAW
|
||||
})
|
||||
.then(() => {
|
||||
this.verbose(1, `Dropped foreign key ${r.COLUMN_NAME} on table ${tableName}`);
|
||||
})
|
||||
.catch((e) => {
|
||||
this.verbose(
|
||||
1,
|
||||
`Error dropping foreign key ${r.COLUMN_NAME} on table ${tableName}:`,
|
||||
e
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.verbose(1, `Error dropping foreign keys for table ${tableName}:`, error);
|
||||
} finally {
|
||||
model.sync();
|
||||
}
|
||||
}
|
||||
await this.models.Player.sync();
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import Rcon from 'core/rcon';
|
||||
export default class SquadRcon extends Rcon {
|
||||
processChatPacket(decodedPacket) {
|
||||
const matchChat = decodedPacket.body.match(
|
||||
/\[(ChatAll|ChatTeam|ChatSquad|ChatAdmin)] \[SteamID:([0-9]{17})] (.+?) : (.*)/
|
||||
/\[(ChatAll|ChatTeam|ChatSquad|ChatAdmin)] \[Online IDs:EOS: ([0-9a-f]{32}) steam: (\d{17})\] (.+?) : (.*)/
|
||||
);
|
||||
if (matchChat) {
|
||||
Logger.verbose('SquadRcon', 2, `Matched chat message: ${decodedPacket.body}`);
|
||||
@ -12,9 +12,10 @@ export default class SquadRcon extends Rcon {
|
||||
this.emit('CHAT_MESSAGE', {
|
||||
raw: decodedPacket.body,
|
||||
chat: matchChat[1],
|
||||
steamID: matchChat[2],
|
||||
name: matchChat[3],
|
||||
message: matchChat[4],
|
||||
eosID: matchChat[2],
|
||||
steamID: matchChat[3],
|
||||
name: matchChat[4],
|
||||
message: matchChat[5],
|
||||
time: new Date()
|
||||
});
|
||||
|
||||
@ -22,14 +23,14 @@ export default class SquadRcon extends Rcon {
|
||||
}
|
||||
|
||||
const matchPossessedAdminCam = decodedPacket.body.match(
|
||||
/\[SteamID:([0-9]{17})] (.+?) has possessed admin camera./
|
||||
/\[Online Ids:EOS: ([0-9a-f]{32}) steam: (\d{17})\] (.+) has possessed admin camera\./
|
||||
);
|
||||
if (matchPossessedAdminCam) {
|
||||
Logger.verbose('SquadRcon', 2, `Matched admin camera possessed: ${decodedPacket.body}`);
|
||||
this.emit('POSSESSED_ADMIN_CAMERA', {
|
||||
raw: decodedPacket.body,
|
||||
steamID: matchPossessedAdminCam[1],
|
||||
name: matchPossessedAdminCam[2],
|
||||
steamID: matchPossessedAdminCam[2],
|
||||
name: matchPossessedAdminCam[3],
|
||||
time: new Date()
|
||||
});
|
||||
|
||||
@ -37,14 +38,14 @@ export default class SquadRcon extends Rcon {
|
||||
}
|
||||
|
||||
const matchUnpossessedAdminCam = decodedPacket.body.match(
|
||||
/\[SteamID:([0-9]{17})] (.+?) has unpossessed admin camera./
|
||||
/\[Online IDs:EOS: ([0-9a-f]{32}) steam: (\d{17})\] (.+) has unpossessed admin camera\./
|
||||
);
|
||||
if (matchUnpossessedAdminCam) {
|
||||
Logger.verbose('SquadRcon', 2, `Matched admin camera possessed: ${decodedPacket.body}`);
|
||||
this.emit('UNPOSSESSED_ADMIN_CAMERA', {
|
||||
raw: decodedPacket.body,
|
||||
steamID: matchUnpossessedAdminCam[1],
|
||||
name: matchUnpossessedAdminCam[2],
|
||||
steamID: matchUnpossessedAdminCam[2],
|
||||
name: matchUnpossessedAdminCam[3],
|
||||
time: new Date()
|
||||
});
|
||||
|
||||
@ -68,7 +69,7 @@ export default class SquadRcon extends Rcon {
|
||||
}
|
||||
|
||||
const matchKick = decodedPacket.body.match(
|
||||
/Kicked player ([0-9]+)\. \[steamid=([0-9]{17})] (.*)/
|
||||
/Kicked player ([0-9]+)\. \[Online IDs= EOS: ([0-9a-f]{32}) steam: (\d{17})] (.*)/
|
||||
);
|
||||
if (matchKick) {
|
||||
Logger.verbose('SquadRcon', 2, `Matched kick message: ${decodedPacket.body}`);
|
||||
@ -76,8 +77,8 @@ export default class SquadRcon extends Rcon {
|
||||
this.emit('PLAYER_KICKED', {
|
||||
raw: decodedPacket.body,
|
||||
playerID: matchKick[1],
|
||||
steamID: matchKick[2],
|
||||
name: matchKick[3],
|
||||
steamID: matchKick[3],
|
||||
name: matchKick[4],
|
||||
time: new Date()
|
||||
});
|
||||
|
||||
@ -85,18 +86,14 @@ export default class SquadRcon extends Rcon {
|
||||
}
|
||||
|
||||
const matchSqCreated = decodedPacket.body.match(
|
||||
/(.+) \(Steam ID: ([0-9]{17})\) has created Squad (\d+) \(Squad Name: (.+)\) on (.+)/
|
||||
/(?<playerName>.+) \(Online IDs: EOS: (?<playerEOSID>[\da-f]{32})(?: steam: (?<playerSteamID>\d{17}))?\) has created Squad (?<squadID>\d+) \(Squad Name: (?<squadName>.+)\) on (?<teamName>.+)/
|
||||
);
|
||||
if (matchSqCreated) {
|
||||
Logger.verbose('SquadRcon', 2, `Matched Squad Created: ${decodedPacket.body}`);
|
||||
|
||||
this.emit('SQUAD_CREATED', {
|
||||
time: new Date(),
|
||||
playerName: matchSqCreated[1],
|
||||
playerSteamID: matchSqCreated[2],
|
||||
squadID: matchSqCreated[3],
|
||||
squadName: matchSqCreated[4],
|
||||
teamName: matchSqCreated[5]
|
||||
...matchSqCreated.groups
|
||||
});
|
||||
|
||||
return;
|
||||
@ -143,19 +140,17 @@ export default class SquadRcon extends Rcon {
|
||||
|
||||
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) \| Is Leader: (True|False) \| Role: ([A-Za-z0-9_]*)\b/
|
||||
/^ID: (?<playerID>\d+) \| Online IDs: EOS: (?<eosID>[a-f\d]{32}) (?:steam: (?<steamID>\d{17}) )?\| Name: (?<name>.+) \| Team ID: (?<teamID>\d|N\/A) \| Squad ID: (?<squadID>\d+|N\/A) \| Is Leader: (?<isLeader>True|False) \| Role: (?<role>.+)$/
|
||||
);
|
||||
if (!match) continue;
|
||||
|
||||
players.push({
|
||||
playerID: match[1],
|
||||
steamID: match[2],
|
||||
name: match[3],
|
||||
teamID: match[4],
|
||||
squadID: match[5] !== 'N/A' ? match[5] : null,
|
||||
isLeader: match[6] === 'True',
|
||||
role: match[7]
|
||||
});
|
||||
const data = match.groups;
|
||||
data.playerID = +data.playerID;
|
||||
data.isLeader = data.isLeader === 'True';
|
||||
data.teamID = data.teamID !== 'N/A' ? +data.teamID : null;
|
||||
data.squadID = data.squadID !== 'N/A' ? +data.squadID : null;
|
||||
|
||||
players.push(data);
|
||||
}
|
||||
|
||||
return players;
|
||||
@ -172,21 +167,17 @@ export default class SquadRcon extends Rcon {
|
||||
|
||||
for (const line of responseSquad.split('\n')) {
|
||||
const match = line.match(
|
||||
/ID: ([0-9]+) \| Name: (.+) \| Size: ([0-9]+) \| Locked: (True|False) \| Creator Name: (.+) \| Creator Steam ID: ([0-9]{17})/
|
||||
/ID: (?<squadID>\d+) \| Name: (?<squadName>.+) \| Size: (?<size>\d+) \| Locked: (?<locked>True|False) \| Creator Name: (?<creatorName>.+) \| Creator Online IDs: EOS: (?<creatorEOSID>[a-f\d]{32})(?: steam: (?<creatorSteamID>\d{17}))?/
|
||||
);
|
||||
const matchSide = line.match(/Team ID: (1|2) \((.+)\)/);
|
||||
const matchSide = line.match(/Team ID: (\d) \((.+)\)/);
|
||||
if (matchSide) {
|
||||
teamID = matchSide[1];
|
||||
teamID = +matchSide[1];
|
||||
teamName = matchSide[2];
|
||||
}
|
||||
if (!match) continue;
|
||||
match.groups.squadID = +match.groups.squadID;
|
||||
squads.push({
|
||||
squadID: match[1],
|
||||
squadName: match[2],
|
||||
size: match[3],
|
||||
locked: match[4],
|
||||
creatorName: match[5],
|
||||
creatorSteamID: match[6],
|
||||
...match.groups,
|
||||
teamID: teamID,
|
||||
teamName: teamName
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user