Jackpot (scrap 500), Santa Claus (supply.signal 1), Care Package (l96.weapon 1), Emergency Heal (large.medkit 3), and Loot Reset (server.fill_groups - map-wide, with confirm dialog). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
186 lines
7.7 KiB
JavaScript
186 lines
7.7 KiB
JavaScript
/**
|
|
* Player info page — single player detail with quirk fixes.
|
|
*/
|
|
function PlayerInfoPage(params, container) {
|
|
var userid = params[2]; // SteamID from URL
|
|
|
|
var html =
|
|
'<div id="PlayerInfoController">' +
|
|
'<div class="row">' +
|
|
'<div class="col-lg-12">' +
|
|
'<h2 class="text-center">' +
|
|
'Player: <span id="pi-username">' + userid + '</span>' +
|
|
'<button id="pi-refresh" class="btn btn-secondary float-end" type="button"><i class="bi bi-arrow-clockwise"></i></button>' +
|
|
'</h2>' +
|
|
'<div class="btn-group d-flex mb-3">' +
|
|
'<a href="http://www.steamcommunity.com/profiles/' + userid + '" target="_blank" class="btn btn-secondary">' +
|
|
'<i class="bi bi-info-circle-fill"></i> Steam Profile' +
|
|
'</a>' +
|
|
'<button id="pi-kick" class="btn btn-warning"><i class="bi bi-trash-fill"></i> Kick</button>' +
|
|
'<button id="pi-ban" class="btn btn-danger"><i class="bi bi-ban-fill"></i> Ban</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'<div class="col-lg-12">' +
|
|
'<div id="pi-notfound" class="alert alert-warning" style="display:none">This Player is currently not connected to this server!</div>' +
|
|
'</div>' +
|
|
'<div class="col-lg-12">' +
|
|
'<div id="pi-fields" class="row"><span class="text-white-50">Loading…</span></div>' +
|
|
'</div>' +
|
|
'<div id="pi-actions" class="col-lg-12 mt-3" style="display:none">' +
|
|
'<div class="btn-group d-flex mb-2">' +
|
|
'<button id="pi-kill" class="btn btn-outline-danger"><i class="bi bi-skull"></i> Kill</button>' +
|
|
'<button id="pi-heal" class="btn btn-outline-success"><i class="bi bi-heart-fill"></i> Heal</button>' +
|
|
'<button id="pi-give" class="btn btn-outline-purple"><i class="bi bi-gift-fill"></i> Give Item</button>' +
|
|
'<button id="pi-teleport" class="btn btn-outline-info"><i class="bi bi-signpost-2-fill"></i> Teleport To</button>' +
|
|
'</div>' +
|
|
'<div class="btn-group d-flex mb-2">' +
|
|
'<button id="pi-mod" class="btn btn-outline-info"><i class="bi bi-shield-check"></i> Moderator</button>' +
|
|
'<button id="pi-owner" class="btn btn-outline-warning"><i class="bi bi-star-fill"></i> Owner</button>' +
|
|
'</div>' +
|
|
'<div class="btn-group d-flex">' +
|
|
'<button id="pi-scrap" class="btn btn-outline-warning"><i class="bi bi-cash-stack"></i> Jackpot</button>' +
|
|
'<button id="pi-airdrop" class="btn btn-outline-info"><i class="bi bi-send-fill"></i> Santa Claus</button>' +
|
|
'<button id="pi-sniper" class="btn btn-outline-danger"><i class="bi bi-crosshair"></i> Care Package</button>' +
|
|
'<button id="pi-medkit" class="btn btn-outline-success"><i class="bi bi-heart-pulse-fill"></i> Emergency Heal</button>' +
|
|
'<button id="pi-lootreset" class="btn btn-outline-purple"><i class="bi bi-arrow-repeat"></i> Loot Reset</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
container.innerHTML = html;
|
|
|
|
function refresh() {
|
|
Rcon.getPlayers(function (players) {
|
|
// Guard against navigation away while waiting for RCON response
|
|
var nf = document.getElementById('pi-notfound');
|
|
var fields = document.getElementById('pi-fields');
|
|
var actions = document.getElementById('pi-actions');
|
|
if (!nf || !fields || !actions) return;
|
|
|
|
var info = null;
|
|
for (var i = 0; i < players.length; i++) {
|
|
if (String(players[i].SteamID) === userid) { info = players[i]; break; }
|
|
}
|
|
|
|
if (!info) {
|
|
nf.style.display = 'block';
|
|
fields.innerHTML = '';
|
|
actions.style.display = 'none';
|
|
return;
|
|
}
|
|
nf.style.display = 'none';
|
|
actions.style.display = 'block';
|
|
|
|
// Fix known Rust RCON quirk: VoiationLevel → ViolationLevel
|
|
if (info.VoiationLevel !== undefined) {
|
|
info.ViolationLevel = info.VoiationLevel;
|
|
delete info.VoiationLevel;
|
|
}
|
|
|
|
// Remove XP remnants
|
|
delete info.CurrentLevel;
|
|
delete info.UnspentXp;
|
|
|
|
var un = document.getElementById('pi-username');
|
|
if (un) un.textContent = info.DisplayName || userid;
|
|
|
|
var fieldsHtml = '';
|
|
for (var key in info) {
|
|
if (info.hasOwnProperty(key)) {
|
|
var value = info[key];
|
|
if (key === 'Address') {
|
|
value = maskIp(value);
|
|
} else if (typeof value === 'object' && value !== null) {
|
|
// e.g. Position: {x, y, z}
|
|
value = 'x:' + (value.x || 0).toFixed(1) + ' y:' + (value.y || 0).toFixed(1) + ' z:' + (value.z || 0).toFixed(1);
|
|
}
|
|
fieldsHtml += '<div class="col-sm-4"><p>' + key + ': <span class="badge">' + value + '</span></p></div>';
|
|
}
|
|
}
|
|
fields.innerHTML = fieldsHtml;
|
|
});
|
|
}
|
|
|
|
document.getElementById('pi-refresh').addEventListener('click', refresh);
|
|
|
|
document.getElementById('pi-kick').addEventListener('click', function () {
|
|
if (confirm('Kick player ' + (document.getElementById('pi-username').textContent) + '?')) {
|
|
Rcon.command('kick ' + userid);
|
|
}
|
|
});
|
|
|
|
document.getElementById('pi-ban').addEventListener('click', function () {
|
|
var reason = prompt('Ban reason:', '');
|
|
if (reason !== null) {
|
|
Rcon.command('ban ' + userid + ' ' + (reason || 'No reason'));
|
|
}
|
|
});
|
|
|
|
var pname = document.getElementById('pi-username');
|
|
|
|
document.getElementById('pi-kill').addEventListener('click', function () {
|
|
if (confirm('Kill ' + pname.textContent + '?')) {
|
|
Rcon.command('global.kill ' + userid);
|
|
}
|
|
});
|
|
|
|
document.getElementById('pi-heal').addEventListener('click', function () {
|
|
if (confirm('Heal ' + pname.textContent + '?')) {
|
|
Rcon.command('heal ' + userid);
|
|
}
|
|
});
|
|
|
|
document.getElementById('pi-give').addEventListener('click', function () {
|
|
var item = prompt('Item shortname (e.g. wood, rifle.ak):', '');
|
|
if (!item) return;
|
|
var amount = prompt('Amount (default 1):', '1');
|
|
if (amount === null) return;
|
|
Rcon.command('inventory.giveto ' + userid + ' ' + item.trim() + ' ' + (parseInt(amount) || 1));
|
|
});
|
|
|
|
document.getElementById('pi-teleport').addEventListener('click', function () {
|
|
var target = prompt('Teleport ' + pname.textContent + ' to SteamID:', '');
|
|
if (target) {
|
|
Rcon.command('entity.teleport ' + userid + ' ' + target.trim());
|
|
}
|
|
});
|
|
|
|
// ---- Quick rewards ----
|
|
document.getElementById('pi-scrap').addEventListener('click', function () {
|
|
Rcon.command('inventory.giveto ' + userid + ' scrap 500');
|
|
});
|
|
|
|
document.getElementById('pi-airdrop').addEventListener('click', function () {
|
|
Rcon.command('inventory.giveto ' + userid + ' supply.signal 1');
|
|
});
|
|
|
|
document.getElementById('pi-sniper').addEventListener('click', function () {
|
|
Rcon.command('inventory.giveto ' + userid + ' l96.weapon 1');
|
|
});
|
|
|
|
document.getElementById('pi-medkit').addEventListener('click', function () {
|
|
Rcon.command('inventory.giveto ' + userid + ' large.medkit 3');
|
|
});
|
|
|
|
document.getElementById('pi-lootreset').addEventListener('click', function () {
|
|
if (confirm('Respawn all loot crates and barrels across the entire map?')) {
|
|
Rcon.command('server.fill_groups');
|
|
}
|
|
});
|
|
|
|
document.getElementById('pi-mod').addEventListener('click', function () {
|
|
if (confirm('Promote ' + pname.textContent + ' to Moderator?')) {
|
|
Rcon.command('moderatorid ' + userid + ' ' + pname.textContent);
|
|
}
|
|
});
|
|
|
|
document.getElementById('pi-owner').addEventListener('click', function () {
|
|
if (confirm('Promote ' + pname.textContent + ' to Owner?')) {
|
|
Rcon.command('ownerid ' + userid + ' ' + pname.textContent);
|
|
}
|
|
});
|
|
|
|
if (Rcon.isConnected()) refresh();
|
|
else { var _c = function () { refresh(); Rcon.off('connected', _c); }; Rcon.on('connected', _c); }
|
|
}
|