add de_rainfall

This commit is contained in:
shoopea
2026-06-22 19:33:34 +02:00
parent f272a053a8
commit 382a648f41
2 changed files with 680 additions and 627 deletions
+291 -274
View File
@@ -1,15 +1,15 @@
$(document).ready(function () { $(document).ready(function () {
const current_path = window.location.pathname; const current_path = window.location.pathname;
function fetch_servers() { function fetch_servers() {
$.ajax({ $.ajax({
url: '/api/servers', url: "/api/servers",
type: 'GET', type: "GET",
success: function (data) { success: function (data) {
$('#serverList').empty(); $("#serverList").empty();
data.servers.forEach(function (server) { data.servers.forEach(function (server) {
const card = ` const card = `
<div class="card server-card"> <div class="card server-card">
<div class="card-header"> <div class="card-header">
<h3 class="card-title">${server.hostname} (${server.serverIP}:${server.serverPort})</h3> <h3 class="card-title">${server.hostname} (${server.serverIP}:${server.serverPort})</h3>
@@ -19,283 +19,300 @@ $(document).ready(function () {
<button class="btn btn-sm btn-secondary toggle-password" server-id="${server.id}" class="hide-unhide-rcon"> <button class="btn btn-sm btn-secondary toggle-password" server-id="${server.id}" class="hide-unhide-rcon">
<i class="fa fa-eye" server-id="${server.id}" id="toggleEyeIcon-${server.id}"></i> <i class="fa fa-eye" server-id="${server.id}" id="toggleEyeIcon-${server.id}"></i>
</button> </button>
<p class="status connected-status ${server.connected ? 'connected' : 'disconnected'}"> <p class="status connected-status ${server.connected ? "connected" : "disconnected"}">
RCON Connected: ${server.connected ? 'Yes' : 'No'} RCON Connected: ${server.connected ? "Yes" : "No"}
</p> </p>
<p class="status authenticated-status ${server.authenticated ? 'authenticated' : 'not-authenticated'}"> <p class="status authenticated-status ${server.authenticated ? "authenticated" : "not-authenticated"}">
RCON Authenticated: ${server.authenticated ? 'Yes' : 'No'} RCON Authenticated: ${server.authenticated ? "Yes" : "No"}
</p> </p>
${(!server.connected || !server.authenticated) ? '<button class="btn btn-success" server-id="' + server.id + '" id="reconnect_server">Reconnect</button>' : ''} ${!server.connected || !server.authenticated ? '<button class="btn btn-success" server-id="' + server.id + '" id="reconnect_server">Reconnect</button>' : ""}
<a href="/manage/${server.id}" class="btn btn-primary">Manage</a> <a href="/manage/${server.id}" class="btn btn-primary">Manage</a>
<button class="btn btn-danger" server-id='${server.id}' id="delete_server">Delete</button> <button class="btn btn-danger" server-id='${server.id}' id="delete_server">Delete</button>
</div> </div>
</div> </div>
`; `;
$('#serverList').append(card); $("#serverList").append(card);
});
$(".toggle-password").click((event) => {
let server_id = $(event.target).attr("server-id");
toggle_password_visibility(server_id)
});
$("#reconnect_server").click(async (element) => {
try {
const server_id = $(element.target).attr("server-id");
const response = await $.ajax({
url: '/api/reconnect-server',
type: 'POST',
data: JSON.stringify({ server_id: server_id }),
headers: {
'Content-Type': 'application/json',
},
});
if (response.status === 200) {
fetch_servers();
} else {
console.error('Server responded with a non-200 status code:', response.status);
alert('An error occurred while reconnecting to the server.');
}
} catch (error) {
console.error(error);
alert('An error occurred while reconnecting to the server.');
}
});
$("#delete_server").click(async (element) => {
const confirmed = confirm("Are you sure you want to delete this server?");
if (confirmed) {
window.server_id = $(element.target).attr("server-id");
await send_post_request("/api/delete-server");
fetch_servers();
}
});
},
error: function (error) {
console.error(error);
alert('An error occurred while fetching servers.');
},
}); });
} $(".toggle-password").click((event) => {
if (current_path == "/servers") { let server_id = $(event.target).attr("server-id");
fetch_servers(); toggle_password_visibility(server_id);
} });
$("#reconnect_server").click(async (element) => {
function toggle_password_visibility(server_id) { try {
const password_field = document.getElementsByClassName("rcon-password-" + server_id)[0] const server_id = $(element.target).attr("server-id");
const eye_icon = document.getElementById(`toggleEyeIcon-${server_id}`); const response = await $.ajax({
url: "/api/reconnect-server",
if (password_field.type === 'password') { type: "POST",
password_field.type = 'text'; data: JSON.stringify({ server_id: server_id }),
eye_icon.classList.remove('fa-eye'); headers: {
eye_icon.classList.add('fa-eye-slash'); "Content-Type": "application/json",
} else { },
password_field.type = 'password';
eye_icon.classList.remove('fa-eye-slash');
eye_icon.classList.add('fa-eye');
}
}
async function send_post_request(apiEndpoint, data = {}) {
try {
data.server_id = window.server_id
const response = await fetch(apiEndpoint, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
}); });
if (response.status === 200) {
if (response.ok) { fetch_servers();
const data = await response.json(); } else {
console.log(data.message) console.error(
if(apiEndpoint == '/api/rcon') { "Server responded with a non-200 status code:",
if (data.message.includes("Response received")) { response.status,
$('#rconResultBox').show(); );
$('#rconResultText').text(data.message.split("Command sent! Response received:")[1]); alert("An error occurred while reconnecting to the server.");
} else {
$('#rconResultBox').hide();
alert(data.message);
}
} else {
alert(data.message);
}
} else if (response.status == 401) {
alert('Unauthorized, please reload and relogin.');
}
else {
alert('Failed to perform the action');
} }
} catch (error) { } catch (error) {
console.error('Error:', error); console.error(error);
alert('An error occurred'); alert("An error occurred while reconnecting to the server.");
}
});
$("#delete_server").click(async (element) => {
const confirmed = confirm(
"Are you sure you want to delete this server?",
);
if (confirmed) {
window.server_id = $(element.target).attr("server-id");
await send_post_request("/api/delete-server");
fetch_servers();
}
});
},
error: function (error) {
console.error(error);
alert("An error occurred while fetching servers.");
},
});
}
if (current_path == "/servers") {
fetch_servers();
}
function toggle_password_visibility(server_id) {
const password_field = document.getElementsByClassName(
"rcon-password-" + server_id,
)[0];
const eye_icon = document.getElementById(`toggleEyeIcon-${server_id}`);
if (password_field.type === "password") {
password_field.type = "text";
eye_icon.classList.remove("fa-eye");
eye_icon.classList.add("fa-eye-slash");
} else {
password_field.type = "password";
eye_icon.classList.remove("fa-eye-slash");
eye_icon.classList.add("fa-eye");
}
}
async function send_post_request(apiEndpoint, data = {}) {
try {
data.server_id = window.server_id;
const response = await fetch(apiEndpoint, {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
});
if (response.ok) {
const data = await response.json();
console.log(data.message);
if (apiEndpoint == "/api/rcon") {
if (data.message.includes("Response received")) {
$("#rconResultBox").show();
$("#rconResultText").text(
data.message.split("Command sent! Response received:")[1],
);
} else {
$("#rconResultBox").hide();
alert(data.message);
}
} else {
alert(data.message);
} }
} else if (response.status == 401) {
alert("Unauthorized, please reload and relogin.");
} else {
alert("Failed to perform the action");
}
} catch (error) {
console.error("Error:", error);
alert("An error occurred");
}
}
$("#pause_game").on("click", function () {
if (confirm("Are you sure you want to pause the game?")) {
send_post_request("/api/pause");
}
});
$("#unpause_game").on("click", function () {
if (confirm("Are you sure you want to unpause the game?")) {
send_post_request("/api/unpause");
}
});
$("#restart_game").on("click", function () {
if (confirm("Are you sure you want to restart the game?")) {
send_post_request("/api/restart");
}
});
$("#start_warmup").on("click", function () {
if (confirm("Are you sure you want to start the warm-up?")) {
send_post_request("/api/start-warmup");
}
});
$("#swap_team").on("click", function () {
if (confirm("Are you sure you want to swap teams?")) {
send_post_request("/api/swap-team");
}
});
$("#go_live").on("click", function () {
if (confirm("Are you sure you want to go live?")) {
send_post_request("/api/go-live");
}
});
$("#rconInputBtn").on("click", function () {
let data = {
command: $("#rconInput").val(),
};
send_post_request("/api/rcon", data);
$("#rconInput").val("");
});
$("#say_input_btn").on("click", function () {
let data = {
message: $("#say_input").val(),
};
send_post_request("/api/say-admin", data);
$("#say_input").val("");
});
$("#list_backups").on("click", function () {
send_post_request("/api/list-backups");
});
$("#restore_latest_backup").on("click", function () {
if (confirm("Are you sure you want to restore the latest round backup?")) {
send_post_request("/api/restore-latest-backup");
}
});
$("#restore_backup").on("click", function () {
const round_number = prompt("Enter round number to restore:");
if (round_number !== null && round_number.trim() !== "") {
const round_number_value = parseInt(round_number);
if (!isNaN(round_number_value)) {
send_post_request("/api/restore-round", {
round_number: round_number_value,
});
} else {
alert("Invalid round number. Please enter a valid number.");
}
} else {
alert("Round number cannot be empty. Please enter a valid number.");
}
});
$("#server_setup_form").on("submit", async function (event) {
event.preventDefault();
const data = {
team1: $("#team1").val(),
team2: $("#team2").val(),
map: $("#map").val(),
game: $("#game").val(),
server_id: window.server_id,
};
send_post_request("/api/setup-game", data);
});
$("#game").on("change", function () {
var map_list = [];
var e = document.getElementById("game");
if (e.value == "1" || e.value == "2" || e.value == "3" || e.value == "4") {
// CASUAL OR COMPETITIVE
// CS maps
//map_list.push("cs_agency");
map_list.push("cs_italy");
map_list.push("cs_office");
// DE maps (community)
//map_list.push("de_basalt");
map_list.push("de_edin"); // 3328169568
map_list.push("de_grail"); // 3246527710
//map_list.push("de_golden");
//map_list.push("de_jura");
//map_list.push("de_mills");
//map_list.push("de_palacio");
map_list.push("de_thera"); // 3121217565
map_list.push("de_warden");
// DE maps (valve)
map_list.push("de_ancient");
map_list.push("de_ancient_night");
map_list.push("de_anubis");
map_list.push("de_cache");
map_list.push("de_dust2");
map_list.push("de_inferno");
map_list.push("de_mirage");
map_list.push("de_nuke");
map_list.push("de_overpass");
map_list.push("de_train");
map_list.push("de_vertigo");
// WINGMAN maps
map_list.push("de_assembly"); // 3071005299
map_list.push("de_brewery"); // 2870304806
map_list.push("de_dogtown"); // 3414036782
//map_list.push("de_maginot"); // 3195399109
map_list.push("de_memento"); // 3165559377
map_list.push("de_mirage_bricks"); // 3464733042
map_list.push("de_palais"); // 3257582863
map_list.push("de_poseidon");
map_list.push("de_rainfall"); // 3265650949
map_list.push("de_rooftop"); // 3536622725
map_list.push("de_sanctum");
map_list.push("de_transit"); // 3542662073
map_list.push("de_whistle"); // 3308613773
} else if (e.value == "5") {
// WINGMAN
// DE maps (valve)
map_list.push("de_inferno");
map_list.push("de_nuke");
map_list.push("de_overpass");
map_list.push("de_vertigo");
// Community maps
map_list.push("de_assembly"); // 3071005299
map_list.push("de_brewery"); // 2870304806
map_list.push("de_dogtown"); // 3414036782
//map_list.push("de_maginot"); // 3195399109
map_list.push("de_memento"); // 3165559377
map_list.push("de_mirage_bricks"); // 3464733042
map_list.push("de_palais"); // 3257582863
map_list.push("de_poseidon");
map_list.push("de_rainfall"); // 3265650949
map_list.push("de_rooftop"); // 3536622725
map_list.push("de_sanctum");
map_list.push("de_transit"); // 3542662073
map_list.push("de_whistle"); // 3308613773
} else if (e.value == "6") {
// arms race
map_list.push("ar_baggage");
map_list.push("ar_pool_day");
map_list.push("ar_shoots");
map_list.push("ar_shoots_night");
} else if (e.value == "7") {
// other
// WORKSHOP
map_list.push("de_inferno_prophunt"); // 3608612434
map_list.push("cs_office_prophunt"); // 3644811896
map_list.push("de_mirage_prophunt"); // 3615968422
} }
$('#pause_game').on('click', function () { $("#map").empty();
if (confirm("Are you sure you want to pause the game?")) {
send_post_request('/api/pause');
}
});
$('#unpause_game').on('click', function () {
if (confirm("Are you sure you want to unpause the game?")) {
send_post_request('/api/unpause');
}
});
$('#restart_game').on('click', function () {
if (confirm("Are you sure you want to restart the game?")) {
send_post_request('/api/restart');
}
});
$('#start_warmup').on('click', function () {
if (confirm("Are you sure you want to start the warm-up?")) {
send_post_request('/api/start-warmup');
}
});
$('#swap_team').on('click', function () {
if (confirm("Are you sure you want to swap teams?")) {
send_post_request('/api/swap-team');
}
});
$('#go_live').on('click', function () {
if (confirm("Are you sure you want to go live?")) {
send_post_request('/api/go-live');
}
});
$('#rconInputBtn').on('click', function () { for (var i = 0; i < map_list.length; i++) {
let data = { const opt =
command: $('#rconInput').val() '<option value="' + map_list[i] + '">' + map_list[i] + "</option>";
}; $("#map").append(opt);
send_post_request('/api/rcon', data); }
$('#rconInput').val(''); });
});
$('#say_input_btn').on('click', function () {
let data = {
message: $('#say_input').val()
};
send_post_request('/api/say-admin', data);
$('#say_input').val('');
});
$('#list_backups').on('click', function () {
send_post_request('/api/list-backups');
});
$('#restore_latest_backup').on('click', function () {
if (confirm("Are you sure you want to restore the latest round backup?")) {
send_post_request('/api/restore-latest-backup');
}
});
$('#restore_backup').on('click', function () {
const round_number = prompt('Enter round number to restore:');
if (round_number !== null && round_number.trim() !== '') {
const round_number_value = parseInt(round_number);
if (!isNaN(round_number_value)) {
send_post_request('/api/restore-round', { round_number: round_number_value });
} else {
alert('Invalid round number. Please enter a valid number.');
}
} else {
alert('Round number cannot be empty. Please enter a valid number.');
}
});
$('#server_setup_form').on('submit', async function (event) {
event.preventDefault();
const data = {
team1: $('#team1').val(),
team2: $('#team2').val(),
map: $('#map').val(),
game: $('#game').val(),
server_id: window.server_id
};
send_post_request('/api/setup-game', data);
});
$('#game').on('change', function () {
var map_list = [];
var e = document.getElementById("game");
if (e.value == "1" || e.value == "2" || e.value == "3" || e.value == "4") { // CASUAL OR COMPETITIVE
// CS maps
//map_list.push("cs_agency");
map_list.push("cs_italy");
map_list.push("cs_office");
// DE maps (community)
//map_list.push("de_basalt");
map_list.push("de_edin"); // 3328169568
map_list.push("de_grail"); // 3246527710
//map_list.push("de_golden");
//map_list.push("de_jura");
//map_list.push("de_mills");
//map_list.push("de_palacio");
map_list.push("de_thera"); // 3121217565
map_list.push("de_warden");
// DE maps (valve)
map_list.push("de_ancient");
map_list.push("de_ancient_night");
map_list.push("de_anubis");
map_list.push("de_cache");
map_list.push("de_dust2");
map_list.push("de_inferno");
map_list.push("de_mirage");
map_list.push("de_nuke");
map_list.push("de_overpass");
map_list.push("de_train");
map_list.push("de_vertigo");
// WINGMAN maps
map_list.push("de_assembly"); // 3071005299
map_list.push("de_brewery"); // 2870304806
map_list.push("de_dogtown"); // 3414036782
//map_list.push("de_maginot"); // 3195399109
map_list.push("de_memento"); // 3165559377
map_list.push("de_mirage_bricks"); // 3464733042
map_list.push("de_palais"); // 3257582863
map_list.push("de_poseidon");
map_list.push("de_rooftop"); // 3536622725
map_list.push("de_sanctum");
map_list.push("de_transit"); // 3542662073
map_list.push("de_whistle"); // 3308613773
} else if (e.value == "5") { // WINGMAN
// DE maps (valve)
map_list.push("de_inferno");
map_list.push("de_nuke");
map_list.push("de_overpass");
map_list.push("de_vertigo");
// Community maps
map_list.push("de_assembly"); // 3071005299
map_list.push("de_brewery"); // 2870304806
map_list.push("de_dogtown"); // 3414036782
//map_list.push("de_maginot"); // 3195399109
map_list.push("de_memento"); // 3165559377
map_list.push("de_mirage_bricks"); // 3464733042
map_list.push("de_palais"); // 3257582863
map_list.push("de_poseidon");
map_list.push("de_rooftop"); // 3536622725
map_list.push("de_sanctum");
map_list.push("de_transit"); // 3542662073
map_list.push("de_whistle"); // 3308613773
} else if (e.value == "6") { // arms race
map_list.push("ar_baggage");
map_list.push("ar_pool_day");
map_list.push("ar_shoots");
map_list.push("ar_shoots_night");
} else if (e.value == "7") { // other
// WORKSHOP
map_list.push("de_inferno_prophunt"); // 3608612434
map_list.push("cs_office_prophunt"); // 3644811896
map_list.push("de_mirage_prophunt"); // 3615968422
}
$('#map').empty();
for (var i = 0; i < map_list.length; i++) {
const opt = '<option value="' + map_list[i] + '">' + map_list[i] + '</option>'
$('#map').append(opt);
}
})
}); });
+389 -353
View File
@@ -1,414 +1,450 @@
const express = require('express'); const express = require("express");
const router = express.Router(); const router = express.Router();
const readline = require('readline'); const readline = require("readline");
const fs = require('fs'); const fs = require("fs");
const rcon = require("../modules/rcon"); const rcon = require("../modules/rcon");
const is_authenticated = require("../modules/middleware"); const is_authenticated = require("../modules/middleware");
const ALLOWED_STEAM_IDS = ['76561198154367261'] const ALLOWED_STEAM_IDS = ["76561198154367261"];
router.post('/api/setup-game', is_authenticated, async (req, res) => { router.post("/api/setup-game", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const team1 = req.body.team1; const team1 = req.body.team1;
const team2 = req.body.team2; const team2 = req.body.team2;
var map = req.body.map; var map = req.body.map;
const game = req.body.game.toString(); const game = req.body.game.toString();
switch(map){ switch (map) {
case "cs_office_prophunt": case "cs_office_prophunt":
map = 3644811896; map = 3644811896;
break; break;
case "de_assembly": case "de_assembly":
map = 3071005299; map = 3071005299;
break; break;
case "de_brewery": case "de_brewery":
map = 2870304806; map = 2870304806;
break; break;
case "de_dogtown": case "de_dogtown":
map = 3414036782; map = 3414036782;
break; break;
case "de_edin": case "de_edin":
map = 3328169568; map = 3328169568;
break; break;
case "de_grail": case "de_grail":
map = 3246527710; map = 3246527710;
break; break;
case "de_inferno_prophunt": case "de_inferno_prophunt":
map = 3608612434; map = 3608612434;
break; break;
case "de_mirage_prophunt": case "de_mirage_prophunt":
map = 3615968422; map = 3615968422;
break; break;
case "de_memento": case "de_memento":
map = 3165559377; map = 3165559377;
break; break;
case "de_maginot": case "de_maginot":
map = 3195399109; map = 3195399109;
break; break;
case "de_mirage_bricks": case "de_mirage_bricks":
map = 3464733042; map = 3464733042;
break; break;
case "de_palais": case "de_palais":
map = 3257582863; map = 3257582863;
break; break;
case "de_rooftop": case "de_rainfall":
map = 3536622725; map = 3265650949;
break; break;
case "de_thera": case "de_rooftop":
map = 3121217565; map = 3536622725;
break; break;
case "de_transit": case "de_thera":
map = 3542662073; map = 3121217565;
break; break;
case "de_whistle": case "de_transit":
map = 3308613773; map = 3542662073;
break; break;
default: case "de_whistle":
map = map; map = 3308613773;
} break;
default:
if (team1.trim() != "") { map = map;
await rcon.execute_command(server_id, `mp_teamname_1 "${team1}"`);
}
if (team2.trim() != "") {
await rcon.execute_command(server_id, `mp_teamname_2 "${team2}"`);
}
if (game == "1") { // Competitive Short
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 1`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, './cfg/live_competitive_16.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "2") { // Competitive Long
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 1`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, './cfg/live_competitive_24.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "3") { // Casual Short
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, './cfg/live_casual_16.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "4") { // Casual Long
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, './cfg/live_casual_24.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "5") { // Wingman
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 2`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, './cfg/live_wingman.cfg');
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "6") { // Arms race
await rcon.execute_command(server_id, `game_type 1`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 10`);
execute_cfg_on_server(server_id, './cfg/live_arms_race.cfg');
} else if (game == "7") { // Prophunt
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, './cfg/live_prophunt.cfg');
}
if (isNaN(map)) {
await rcon.execute_command(server_id, `changelevel ${map}`);
} else {
await rcon.execute_command(server_id, `host_workshop_map ${map}`);
}
// Adding 1 second delay in executing warmup.cfg to make it effective after map has been changed.
if (game == "1" || game == "3" || game == "5") {
setTimeout(() => {
execute_cfg_on_server(server_id, './cfg/warmup_16.cfg');
}, 1000)
} else if (game == "2" || game == "4") {
setTimeout(() => {
execute_cfg_on_server(server_id, './cfg/warmup_24.cfg');
}, 1000)
} else if (game == "6") {
setTimeout(() => {
rcon.execute_command(server_id, `mp_restartgame 30`);
}, 1000)
} else if (game == "7") {
setTimeout(() => {
rcon.execute_command(server_id, 'mp_restartgame 3');
}, 1000)
}
return res.status(200).json({ message: 'Game Created!' });
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
} }
if (team1.trim() != "") {
await rcon.execute_command(server_id, `mp_teamname_1 "${team1}"`);
}
if (team2.trim() != "") {
await rcon.execute_command(server_id, `mp_teamname_2 "${team2}"`);
}
if (game == "1") {
// Competitive Short
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 1`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, "./cfg/live_competitive_16.cfg");
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "2") {
// Competitive Long
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 1`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, "./cfg/live_competitive_24.cfg");
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "3") {
// Casual Short
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, "./cfg/live_casual_16.cfg");
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "4") {
// Casual Long
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, "./cfg/live_casual_24.cfg");
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "5") {
// Wingman
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 2`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, "./cfg/live_wingman.cfg");
await rcon.execute_command(server_id, `mp_warmup_pausetimer 1`);
} else if (game == "6") {
// Arms race
await rcon.execute_command(server_id, `game_type 1`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 10`);
execute_cfg_on_server(server_id, "./cfg/live_arms_race.cfg");
} else if (game == "7") {
// Prophunt
await rcon.execute_command(server_id, `game_type 0`);
await rcon.execute_command(server_id, `game_mode 0`);
await rcon.execute_command(server_id, `sv_skirmish_id 0`);
execute_cfg_on_server(server_id, "./cfg/live_prophunt.cfg");
}
if (isNaN(map)) {
await rcon.execute_command(server_id, `changelevel ${map}`);
} else {
await rcon.execute_command(server_id, `host_workshop_map ${map}`);
}
// Adding 1 second delay in executing warmup.cfg to make it effective after map has been changed.
if (game == "1" || game == "3" || game == "5") {
setTimeout(() => {
execute_cfg_on_server(server_id, "./cfg/warmup_16.cfg");
}, 1000);
} else if (game == "2" || game == "4") {
setTimeout(() => {
execute_cfg_on_server(server_id, "./cfg/warmup_24.cfg");
}, 1000);
} else if (game == "6") {
setTimeout(() => {
rcon.execute_command(server_id, `mp_restartgame 30`);
}, 1000);
} else if (game == "7") {
setTimeout(() => {
rcon.execute_command(server_id, "mp_restartgame 3");
}, 1000);
}
return res.status(200).json({ message: "Game Created!" });
} catch (error) {
console.log(error);
res.status(500).json({ error: "Internal server error" });
}
}); });
router.post('/api/restart', is_authenticated, async (req, res) => { router.post("/api/restart", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
await rcon.execute_command(server_id, `mp_restartgame 1`); await rcon.execute_command(server_id, `mp_restartgame 1`);
return res.status(200).json({ message: 'Game restarted' }); return res.status(200).json({ message: "Game restarted" });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: "Internal server error" });
} }
}); });
router.post('/api/start-warmup', is_authenticated, async (req, res) => { router.post("/api/start-warmup", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
execute_cfg_on_server(server_id, './cfg/warmup.cfg'); execute_cfg_on_server(server_id, "./cfg/warmup.cfg");
execute_cfg_on_server(server_id, './cfg/warmup_restart.cfg'); execute_cfg_on_server(server_id, "./cfg/warmup_restart.cfg");
return res.status(200).json({ message: 'Warmup started!' }); return res.status(200).json({ message: "Warmup started!" });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: "Internal server error" });
} }
}); });
router.post('/api/swap-team', is_authenticated, async (req, res) => { router.post("/api/swap-team", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
await rcon.execute_command(server_id, `mp_swapteams`); await rcon.execute_command(server_id, `mp_swapteams`);
return res.status(200).json({ message: 'Teams Swapped!' }); return res.status(200).json({ message: "Teams Swapped!" });
} catch (error) { } catch (error) {
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: "Internal server error" });
} }
}); });
router.post('/api/go-live', is_authenticated, async (req, res) => { router.post("/api/go-live", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const res_mode = await rcon.execute_command(server_id, `game_mode`); const res_mode = await rcon.execute_command(server_id, `game_mode`);
const game_mode = res_mode.split("=")[1].trim().toString(); const game_mode = res_mode.split("=")[1].trim().toString();
const res_type = await rcon.execute_command(server_id, `game_type`); const res_type = await rcon.execute_command(server_id, `game_type`);
const game_type = res_type.split("=")[1].trim().toString(); const game_type = res_type.split("=")[1].trim().toString();
const res_rounds = await rcon.execute_command(server_id, `mp_maxrounds`); const res_rounds = await rcon.execute_command(server_id, `mp_maxrounds`);
const maxrounds = res_rounds.split("=")[1].trim().toString(); const maxrounds = res_rounds.split("=")[1].trim().toString();
if (game_mode == "1" && maxrounds == "16") { if (game_mode == "1" && maxrounds == "16") {
console.log("Executing live_competitive_16.cfg") console.log("Executing live_competitive_16.cfg");
execute_cfg_on_server(server_id, './cfg/live_competitive_16.cfg'); execute_cfg_on_server(server_id, "./cfg/live_competitive_16.cfg");
} else if (game_mode == "1" && maxrounds == "24") { } else if (game_mode == "1" && maxrounds == "24") {
console.log("Executing live_competitive_24.cfg") console.log("Executing live_competitive_24.cfg");
execute_cfg_on_server(server_id, './cfg/live_competitive_24.cfg'); execute_cfg_on_server(server_id, "./cfg/live_competitive_24.cfg");
} else if (game_mode == "0" && maxrounds == "16") { } else if (game_mode == "0" && maxrounds == "16") {
console.log("Executing live_casual_16.cfg") console.log("Executing live_casual_16.cfg");
execute_cfg_on_server(server_id, './cfg/live_casual_16.cfg'); execute_cfg_on_server(server_id, "./cfg/live_casual_16.cfg");
} else if (game_mode == "0" && maxrounds == "24") { } else if (game_mode == "0" && maxrounds == "24") {
console.log("Executing live_casual_24.cfg") console.log("Executing live_casual_24.cfg");
execute_cfg_on_server(server_id, './cfg/live_casual_24.cfg'); execute_cfg_on_server(server_id, "./cfg/live_casual_24.cfg");
} else if (game_mode == "2") { } else if (game_mode == "2") {
console.log("Executing live_wingman.cfg") console.log("Executing live_wingman.cfg");
execute_cfg_on_server(server_id, './cfg/live_wingman.cfg'); execute_cfg_on_server(server_id, "./cfg/live_wingman.cfg");
}
execute_cfg_on_server(server_id, './cfg/live_restart.cfg');
return res.status(200).json({ message: 'Match is live!!' });
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
} }
execute_cfg_on_server(server_id, "./cfg/live_restart.cfg");
return res.status(200).json({ message: "Match is live!!" });
} catch (error) {
console.log(error);
res.status(500).json({ error: "Internal server error" });
}
}); });
// List Round Backups API // List Round Backups API
router.post('/api/list-backups', is_authenticated, async (req, res) => { router.post("/api/list-backups", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, "mp_backup_restore_list_files"); const response = await rcon.execute_command(
console.log('Server response:', response); server_id,
return res.status(200).json({ message: response }); "mp_backup_restore_list_files",
} catch (error) { );
console.log(error) console.log("Server response:", response);
res.status(500).json({ error: 'Internal server error' }); return res.status(200).json({ message: response });
} } catch (error) {
console.log(error);
res.status(500).json({ error: "Internal server error" });
}
}); });
// Restore Round API // Restore Round API
router.post('/api/restore-round', is_authenticated, async (req, res) => { router.post("/api/restore-round", is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
let round_number = req.body.round_number.toString();
if (round_number.length == 1) {
round_number = "0" + round_number;
}
console.log(
`SENDING mp_backup_restore_load_file backup_round${round_number}.txt`,
);
await rcon.execute_command(
server_id,
`mp_backup_restore_load_file backup_round${round_number}.txt`,
);
await rcon.execute_command(server_id, `mp_pause_match`);
return res.status(200).json({ message: "Round Restored!" });
} catch (error) {
res.status(500).json({ error: "Internal server error" });
}
});
router.post(
"/api/restore-latest-backup",
is_authenticated,
async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
let round_number = req.body.round_number.toString() const response = await rcon.execute_command(
if (round_number.length == 1) { server_id,
round_number = "0" + round_number; `mp_backup_round_file_last`,
} );
console.log(`SENDING mp_backup_restore_load_file backup_round${round_number}.txt`) const last_round_file = response.split("=")[1].trim().toString();
await rcon.execute_command(server_id, `mp_backup_restore_load_file backup_round${round_number}.txt`); if (last_round_file.includes(".txt")) {
await rcon.execute_command(
server_id,
`mp_backup_restore_load_file ${last_round_file}`,
);
await rcon.execute_command(server_id, `mp_pause_match`); await rcon.execute_command(server_id, `mp_pause_match`);
return res.status(200).json({ message: 'Round Restored!' }); return res
.status(200)
.json({ message: `Latest Round Restored! (${last_round_file})` });
} else {
return res.status(200).json({ message: "No latest backup found!" });
}
} catch (error) { } catch (error) {
res.status(500).json({ error: 'Internal server error' }); console.log(error);
res.status(500).json({ error: "Internal server error" });
} }
}); },
);
router.post('/api/restore-latest-backup', is_authenticated, async (req, res) => {
try {
const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, `mp_backup_round_file_last`);
const last_round_file = response.split("=")[1].trim().toString();
if (last_round_file.includes('.txt')) {
await rcon.execute_command(server_id, `mp_backup_restore_load_file ${last_round_file}`);
await rcon.execute_command(server_id, `mp_pause_match`);
return res.status(200).json({ message: `Latest Round Restored! (${last_round_file})` });
} else {
return res.status(200).json({ message: 'No latest backup found!' });
}
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Pause Game API // Pause Game API
router.post('/api/pause', is_authenticated, async (req, res) => { router.post("/api/pause", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, 'mp_pause_match'); const response = await rcon.execute_command(server_id, "mp_pause_match");
return res.status(200).json({ message: 'Game paused' }); return res.status(200).json({ message: "Game paused" });
} catch (error) { } catch (error) {
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: "Internal server error" });
} }
}); });
// Unpause Game API // Unpause Game API
router.post('/api/unpause', is_authenticated, async (req, res) => { router.post("/api/unpause", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const response = await rcon.execute_command(server_id, 'mp_unpause_match'); const response = await rcon.execute_command(server_id, "mp_unpause_match");
return res.status(200).json({ message: 'Game unpaused' }); return res.status(200).json({ message: "Game unpaused" });
} catch (error) { } catch (error) {
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: "Internal server error" });
} }
}); });
router.post('/api/rcon', is_authenticated, async (req, res) => { router.post("/api/rcon", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const command = req.body.command; const command = req.body.command;
const response = await rcon.execute_command(server_id, command); const response = await rcon.execute_command(server_id, command);
if (response == 200) { if (response == 200) {
return res.status(200).json({ message: 'Command sent!' }); return res.status(200).json({ message: "Command sent!" });
}
return res.status(200).json({ message: 'Command sent! Response received:\n' + response.toString() });
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
} }
return res
.status(200)
.json({
message: "Command sent! Response received:\n" + response.toString(),
});
} catch (error) {
res.status(500).json({ error: "Internal server error" });
}
}); });
router.post('/api/say-admin', is_authenticated, async (req, res) => { router.post("/api/say-admin", is_authenticated, async (req, res) => {
try { try {
const server_id = req.body.server_id; const server_id = req.body.server_id;
const message = req.body.message; const message = req.body.message;
const message_to_send = "say " + message; const message_to_send = "say " + message;
await rcon.execute_command(server_id, message_to_send); await rcon.execute_command(server_id, message_to_send);
return res.status(200).json({ message: 'Message sent!' }); return res.status(200).json({ message: "Message sent!" });
} catch (error) { } catch (error) {
res.status(500).json({ error: 'Internal server error' }); res.status(500).json({ error: "Internal server error" });
} }
}); });
function check_whitelisted_players() { function check_whitelisted_players() {
rcon.rcons[server_id].execute('status_json') rcon.rcons[server_id]
.then((response) => { .execute("status_json")
console.log(response) .then((response) => {
const server_status = JSON.parse(response) console.log(response);
const players = server_status['server']['clients'] const server_status = JSON.parse(response);
for (var i = 0; i < players.length; i++) { const players = server_status["server"]["clients"];
let player = players[i] for (var i = 0; i < players.length; i++) {
if (!player.bot && player.steamid64.includes('7656') && !ALLOWED_STEAM_IDS.includes(player.steamid64)) { let player = players[i];
console.log(`kick ${player.name}`) if (
rcon.rcons[server_id].execute(`kick ${player.name}`); !player.bot &&
} player.steamid64.includes("7656") &&
} !ALLOWED_STEAM_IDS.includes(player.steamid64)
return; ) {
}) console.log(`kick ${player.name}`);
.catch(console.error); rcon.rcons[server_id].execute(`kick ${player.name}`);
}
}
return;
})
.catch(console.error);
} }
function splitByByteLength(data, length) { function splitByByteLength(data, length) {
const lines = data; const lines = data;
const exportedLines = []; const exportedLines = [];
const lineEndChar = '; ' const lineEndChar = "; ";
let index = 0; let index = 0;
for(let item = 0; item < lines.length; item++) { for (let item = 0; item < lines.length; item++) {
if(typeof exportedLines[index] === "undefined") { if (typeof exportedLines[index] === "undefined") {
exportedLines[index] = ""; exportedLines[index] = "";
}
const lineFormatted = `${lines[item]}${lineEndChar}`;
const lineBytes = Buffer.byteLength(lineFormatted, 'utf8');
const bufferBytes = Buffer.byteLength(exportedLines[index], 'utf8');
if((bufferBytes + lineBytes) < length) {
exportedLines[index] += lineFormatted;
} else {
index++;
}
} }
return exportedLines; const lineFormatted = `${lines[item]}${lineEndChar}`;
} const lineBytes = Buffer.byteLength(lineFormatted, "utf8");
const bufferBytes = Buffer.byteLength(exportedLines[index], "utf8");
if (bufferBytes + lineBytes < length) {
exportedLines[index] += lineFormatted;
} else {
index++;
}
}
return exportedLines;
}
async function execute_cfg_on_server(server_id, cfg_path) { async function execute_cfg_on_server(server_id, cfg_path) {
fs.readFile(cfg_path, "utf8", (err, data) => {
if (err) {
throw err;
}
fs.readFile(cfg_path, 'utf8', (err, data) => { data = data.replace(/^\/\/.*$/m, "");
if (err) { data = data.split("\n");
throw err; const new_data = [];
for (let i = 0; i < data.length; i += 1) {
const line = data[i].trim();
const segments = line.split(" ");
if (segments[0] === "say" || segments.length == 1) {
new_data.push(line);
} else if (segments[0] !== "" && segments[0] !== "//") {
new_data.push(`${segments[0]} ${segments[1].split("\t")[0]}`);
}
}
const exported_lines = splitByByteLength(data, 512);
async function execute_next_item(item) {
try {
if (item < exported_lines.length) {
console.log("Executing on server:", exported_lines[item]);
await rcon.execute_command(server_id, exported_lines[item]);
// Wait for 100ms before moving to the next iteration
setTimeout(() => {
execute_next_item(item + 1);
}, 100);
} }
} catch (error) {
data = data.replace(/^\/\/.*$/m, ''); console.log("[execute_next_item] Error:", error);
data = data.split("\n"); }
const new_data = []; }
for (let i = 0; i < data.length; i += 1) { execute_next_item(0);
const line = data[i].trim(); });
const segments = line.split(' ');
if(segments[0] === 'say' || segments.length == 1) {
new_data.push(line);
} else if (segments[0] !== '' && segments[0] !== '//') {
new_data.push(`${segments[0]} ${segments[1].split('\t')[0]}`);
}
}
const exported_lines = splitByByteLength(data, 512)
async function execute_next_item(item) {
try {
if (item < exported_lines.length) {
console.log("Executing on server:", exported_lines[item]);
await rcon.execute_command(server_id, exported_lines[item]);
// Wait for 100ms before moving to the next iteration
setTimeout(() => {
execute_next_item(item + 1);
}, 100);
}
} catch (error) {
console.log("[execute_next_item] Error:", error)
}
}
execute_next_item(0);
});
} }
module.exports = { module.exports = {
router router,
}; };