X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcommand%2Fsv_cmd.qc;h=43c53792e5a755ea5e991625924974ac30b40f78;hb=fbb96108e5828a7557694db4469c2d0d7c582846;hp=45871b7aeb60ad51101651ca3c019fdcd1c5a4d8;hpb=23ad6cc4775660c14ef42575146550887f44775e;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc index 45871b7ae..43c53792e 100644 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@ -1,3 +1,40 @@ +#include "../../common/command/command.qh" +#include "sv_cmd.qh" +#include "../_all.qh" + +#include "banning.qh" +#include "cmd.qh" +#include "common.qh" +#include "getreplies.qh" +#include "radarmap.qh" + +#include "../anticheat.qh" +#include "../campaign.qh" +#include "../cl_client.qh" +#include "../cl_player.qh" +#include "../g_world.qh" +#include "../ipban.qh" +#include "../playerdemo.qh" +#include "../teamplay.qh" + +#include "../bot/bot.qh" +#include "../bot/navigation.qh" +#include "../bot/scripting.qh" + +#include "../mutators/mutators_include.qh" + +#include "../../common/constants.qh" +#include "../../common/mapinfo.qh" +#include "../../common/notifications.qh" +#include "../../common/teams.qh" +#include "../../common/util.qh" + +#include "../../common/monsters/sv_monsters.qh" + +#include "../../warpzonelib/mathlib.qh" + +void PutObserverInServer (void); + // ===================================================== // Server side game commands code, reworked by Samual // Last updated: December 29th, 2011 @@ -23,7 +60,7 @@ void make_mapinfo_Think() void changematchtime(float delta, float mi, float ma) { float cur; - float new; + float update; float lim; if(delta == 0) @@ -44,21 +81,21 @@ void changematchtime(float delta, float mi, float ma) if(lim == 0) return; // cannot increase any further else if(lim < ma) - new = min(ma, lim + delta); + update = min(ma, lim + delta); else // already above maximum: FAIL return; } else { if(lim == 0) // infinite: try reducing to max, if we are allowed to - new = max(mi, ma); + update = max(mi, ma); else if(lim > mi) // above minimum: decrease - new = max(mi, lim + delta); + update = max(mi, lim + delta); else // already below minimum: FAIL return; } - cvar_set("timelimit", ftos(new / 60)); + cvar_set("timelimit", ftos(update / 60)); } @@ -85,13 +122,13 @@ void GameCommand_adminmsg(float request, float argc) if((targets) && (admin_message)) { - for(;targets;) + for (;targets;) { t = car(targets); targets = cdr(targets); // Check to see if the player is a valid target client = GetFilteredEntity(t); - accepted = VerifyClientEntity(client, TRUE, FALSE); + accepted = VerifyClientEntity(client, true, false); if(accepted <= 0) { @@ -157,9 +194,6 @@ void GameCommand_mobbutcher(float request) ++removed_count; } - FOR_EACH_PLAYER(head) - head.monstercount = 0; - monsters_total = 0; // reset stats? monsters_killed = 0; @@ -216,6 +250,8 @@ void GameCommand_allspec(float request, float argc) FOR_EACH_REALPLAYER(client) { self = client; + if(self.caplayer) + self.caplayer = 0; PutObserverInServer(); ++i; } @@ -242,7 +278,7 @@ void GameCommand_anticheat(float request, float argc) case CMD_REQUEST_COMMAND: { entity client = GetIndexedEntity(argc, 1); - float accepted = VerifyClientEntity(client, FALSE, FALSE); + float accepted = VerifyClientEntity(client, false, false); if(accepted > 0) { @@ -273,77 +309,77 @@ void GameCommand_bbox(float request) { case CMD_REQUEST_COMMAND: { - print("Original size: ", ftos(world.absmin_x), " ", ftos(world.absmin_y), " ", ftos(world.absmin_z)); - print(" ", ftos(world.absmax_x), " ", ftos(world.absmax_y), " ", ftos(world.absmax_z), "\n"); - print("Currently set size: ", ftos(world.mins_x), " ", ftos(world.mins_y), " ", ftos(world.mins_z)); - print(" ", ftos(world.maxs_x), " ", ftos(world.maxs_y), " ", ftos(world.maxs_z), "\n"); + print("Original size: ", ftos(world.absmin.x), " ", ftos(world.absmin.y), " ", ftos(world.absmin.z)); + print(" ", ftos(world.absmax.x), " ", ftos(world.absmax.y), " ", ftos(world.absmax.z), "\n"); + print("Currently set size: ", ftos(world.mins.x), " ", ftos(world.mins.y), " ", ftos(world.mins.z)); + print(" ", ftos(world.maxs.x), " ", ftos(world.maxs.y), " ", ftos(world.maxs.z), "\n"); print("Solid bounding box size:"); - tracebox('1 0 0' * world.absmin_x, - '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z, - '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z, - '1 0 0' * world.absmax_x, + tracebox('1 0 0' * world.absmin.x, + '0 1 0' * world.absmin.y + '0 0 1' * world.absmin.z, + '0 1 0' * world.absmax.y + '0 0 1' * world.absmax.z, + '1 0 0' * world.absmax.x, MOVE_WORLDONLY, world); if(trace_startsolid) - print(" ", ftos(world.absmin_x)); + print(" ", ftos(world.absmin.x)); else - print(" ", ftos(trace_endpos_x)); + print(" ", ftos(trace_endpos.x)); - tracebox('0 1 0' * world.absmin_y, - '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z, - '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z, - '0 1 0' * world.absmax_y, + tracebox('0 1 0' * world.absmin.y, + '1 0 0' * world.absmin.x + '0 0 1' * world.absmin.z, + '1 0 0' * world.absmax.x + '0 0 1' * world.absmax.z, + '0 1 0' * world.absmax.y, MOVE_WORLDONLY, world); if(trace_startsolid) - print(" ", ftos(world.absmin_y)); + print(" ", ftos(world.absmin.y)); else - print(" ", ftos(trace_endpos_y)); + print(" ", ftos(trace_endpos.y)); - tracebox('0 0 1' * world.absmin_z, - '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y, - '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y, - '0 0 1' * world.absmax_z, + tracebox('0 0 1' * world.absmin.z, + '1 0 0' * world.absmin.x + '0 1 0' * world.absmin.y, + '1 0 0' * world.absmax.x + '0 1 0' * world.absmax.y, + '0 0 1' * world.absmax.z, MOVE_WORLDONLY, world); if(trace_startsolid) - print(" ", ftos(world.absmin_z)); + print(" ", ftos(world.absmin.z)); else - print(" ", ftos(trace_endpos_z)); + print(" ", ftos(trace_endpos.z)); - tracebox('1 0 0' * world.absmax_x, - '0 1 0' * world.absmin_y + '0 0 1' * world.absmin_z, - '0 1 0' * world.absmax_y + '0 0 1' * world.absmax_z, - '1 0 0' * world.absmin_x, + tracebox('1 0 0' * world.absmax.x, + '0 1 0' * world.absmin.y + '0 0 1' * world.absmin.z, + '0 1 0' * world.absmax.y + '0 0 1' * world.absmax.z, + '1 0 0' * world.absmin.x, MOVE_WORLDONLY, world); if(trace_startsolid) - print(" ", ftos(world.absmax_x)); + print(" ", ftos(world.absmax.x)); else - print(" ", ftos(trace_endpos_x)); + print(" ", ftos(trace_endpos.x)); - tracebox('0 1 0' * world.absmax_y, - '1 0 0' * world.absmin_x + '0 0 1' * world.absmin_z, - '1 0 0' * world.absmax_x + '0 0 1' * world.absmax_z, - '0 1 0' * world.absmin_y, + tracebox('0 1 0' * world.absmax.y, + '1 0 0' * world.absmin.x + '0 0 1' * world.absmin.z, + '1 0 0' * world.absmax.x + '0 0 1' * world.absmax.z, + '0 1 0' * world.absmin.y, MOVE_WORLDONLY, world); if(trace_startsolid) - print(" ", ftos(world.absmax_y)); + print(" ", ftos(world.absmax.y)); else - print(" ", ftos(trace_endpos_y)); + print(" ", ftos(trace_endpos.y)); - tracebox('0 0 1' * world.absmax_z, - '1 0 0' * world.absmin_x + '0 1 0' * world.absmin_y, - '1 0 0' * world.absmax_x + '0 1 0' * world.absmax_y, - '0 0 1' * world.absmin_z, + tracebox('0 0 1' * world.absmax.z, + '1 0 0' * world.absmin.x + '0 1 0' * world.absmin.y, + '1 0 0' * world.absmax.x + '0 1 0' * world.absmax.y, + '0 0 1' * world.absmin.z, MOVE_WORLDONLY, world); if(trace_startsolid) - print(" ", ftos(world.absmax_z)); + print(" ", ftos(world.absmax.z)); else - print(" ", ftos(trace_endpos_z)); + print(" ", ftos(trace_endpos.z)); print("\n"); return; @@ -479,14 +515,11 @@ void GameCommand_cointoss(float request, float argc) { case CMD_REQUEST_COMMAND: { - entity client; - string result1 = (argv(2) ? strcat("^7", argv(1), "^3!\n") : "^1HEADS^3!\n"); - string result2 = (argv(2) ? strcat("^7", argv(2), "^3!\n") : "^4TAILS^3!\n"); + string result1 = (argv(2) ? strcat("^7", argv(1)) : "^1HEADS"); + string result2 = (argv(2) ? strcat("^7", argv(2)) : "^4TAILS"); string choice = ((random() > 0.5) ? result1 : result2); - FOR_EACH_CLIENT(client) - centerprint(client, strcat("^3Throwing coin... Result: ", choice)); - bprint(strcat("^3Throwing coin... Result: ", choice)); + Send_Notification(NOTIF_ALL, world, MSG_MULTI, MULTI_COINTOSS, choice); return; } @@ -555,7 +588,7 @@ void GameCommand_defer_clear(float request, float argc) if(argc >= 2) { client = GetIndexedEntity(argc, 1); - accepted = VerifyClientEntity(client, TRUE, FALSE); + accepted = VerifyClientEntity(client, true, false); if(accepted > 0) { @@ -842,14 +875,14 @@ void GameCommand_gettaginfo(float request, float argc) v = gettaginfo(tmp_entity, i); print("model ", tmp_entity.model, " frame ", ftos(tmp_entity.frame), " tag ", gettaginfo_name); print(" index ", ftos(i), " parent ", ftos(gettaginfo_parent), "\n"); - print(" vector = ", ftos(v_x), " ", ftos(v_y), " ", ftos(v_z), "\n"); - print(" offset = ", ftos(gettaginfo_offset_x), " ", ftos(gettaginfo_offset_y), " ", ftos(gettaginfo_offset_z), "\n"); - print(" forward = ", ftos(gettaginfo_forward_x), " ", ftos(gettaginfo_forward_y), " ", ftos(gettaginfo_forward_z), "\n"); - print(" right = ", ftos(gettaginfo_right_x), " ", ftos(gettaginfo_right_y), " ", ftos(gettaginfo_right_z), "\n"); - print(" up = ", ftos(gettaginfo_up_x), " ", ftos(gettaginfo_up_y), " ", ftos(gettaginfo_up_z), "\n"); + print(" vector = ", ftos(v.x), " ", ftos(v.y), " ", ftos(v.z), "\n"); + print(" offset = ", ftos(gettaginfo_offset.x), " ", ftos(gettaginfo_offset.y), " ", ftos(gettaginfo_offset.z), "\n"); + print(" forward = ", ftos(gettaginfo_forward.x), " ", ftos(gettaginfo_forward.y), " ", ftos(gettaginfo_forward.z), "\n"); + print(" right = ", ftos(gettaginfo_right.x), " ", ftos(gettaginfo_right.y), " ", ftos(gettaginfo_right.z), "\n"); + print(" up = ", ftos(gettaginfo_up.x), " ", ftos(gettaginfo_up.y), " ", ftos(gettaginfo_up.z), "\n"); if(argc >= 6) { - v_y = -v_y; + v.y = -v.y; localcmd(strcat(argv(4), vtos(v), argv(5), "\n")); } } @@ -1028,13 +1061,13 @@ void GameCommand_moveplayer(float request, float argc) // lets see if the target(s) even actually exist. if((targets) && (destination)) { - for(;targets;) + for (;targets;) { t = car(targets); targets = cdr(targets); // Check to see if the player is a valid target client = GetFilteredEntity(t); - accepted = VerifyClientEntity(client, FALSE, FALSE); + accepted = VerifyClientEntity(client, false, false); if(accepted <= 0) { @@ -1048,6 +1081,8 @@ void GameCommand_moveplayer(float request, float argc) if(!IS_SPEC(client) && !IS_OBSERVER(client)) { self = client; + if(self.caplayer) + self.caplayer = 0; PutObserverInServer(); successful = strcat(successful, (successful ? ", " : ""), client.netname); @@ -1080,7 +1115,7 @@ void GameCommand_moveplayer(float request, float argc) else if(team_id == 0) // auto team { CheckAllowedTeams(client); - team_id = Team_NumberToTeam(FindSmallestTeam(client, FALSE)); + team_id = Team_NumberToTeam(FindSmallestTeam(client, false)); } else { @@ -1153,9 +1188,10 @@ void GameCommand_nospectators(float request) { blockSpectators = 1; entity plr; - FOR_EACH_CLIENT(plr) //give every spectator seconds time to become a player + FOR_EACH_REALCLIENT(plr) //give every spectator seconds time to become a player { if(IS_SPEC(plr) || IS_OBSERVER(plr)) + if(!plr.caplayer) { plr.spectatortime = time; Send_Notification(NOTIF_ONE_ONLY, plr, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime); @@ -1191,7 +1227,7 @@ void GameCommand_playerdemo(float request, float argc) case "read": { client = GetIndexedEntity(argc, 2); - accepted = VerifyClientEntity(client, FALSE, TRUE); + accepted = VerifyClientEntity(client, false, true); if(accepted <= 0) { @@ -1207,7 +1243,7 @@ void GameCommand_playerdemo(float request, float argc) case "write": { client = GetIndexedEntity(argc, 2); - accepted = VerifyClientEntity(client, FALSE, FALSE); + accepted = VerifyClientEntity(client, false, false); if(accepted <= 0) { @@ -1262,7 +1298,7 @@ void GameCommand_printstats(float request) { case CMD_REQUEST_COMMAND: { - DumpStats(FALSE); + DumpStats(false); print("stats dumped.\n"); return; } @@ -1357,7 +1393,8 @@ void GameCommand_shuffleteams(float request) if(teamplay) { entity tmp_player; - float i, x, z, t_teams, t_players, team_color; + int i; + float x, t_teams, t_players, team_color; // count the total amount of players and total amount of teams t_players = 0; @@ -1377,7 +1414,7 @@ void GameCommand_shuffleteams(float request) // build a list of the players in a random order FOR_EACH_PLAYER(tmp_player) { - for(;;) + for (;;) { i = bound(1, floor(random() * maxclients) + 1, maxclients); @@ -1394,7 +1431,7 @@ void GameCommand_shuffleteams(float request) } // finally, from the list made earlier, re-join the players in different order. - for(i = 1; i <= t_teams; ++i) + for (int i = 1; i <= t_teams; ++i) { // find out how many players to assign to this team x = (t_players / t_teams); @@ -1403,7 +1440,7 @@ void GameCommand_shuffleteams(float request) team_color = Team_NumberToTeam(i); // sort through the random list of players made earlier - for(z = 1; z <= maxclients; ++z) + for (int z = 1; z <= maxclients; ++z) { if (!(shuffleteams_teams[i] >= x)) { @@ -1469,7 +1506,7 @@ void GameCommand_stuffto(float request, float argc) if(argv(2)) { entity client = GetIndexedEntity(argc, 1); - float accepted = VerifyClientEntity(client, TRUE, FALSE); + float accepted = VerifyClientEntity(client, true, false); if(accepted > 0) { @@ -1516,71 +1553,73 @@ void GameCommand_trace(float request, float argc) { case "debug": { + float hitcount = 0; print("TEST CASE. If this returns the runaway loop counter error, possibly everything is oaky.\n"); - for(;;) + float worst_endpos_bug = 0; + for (;;) { org = world.mins; delta = world.maxs - world.mins; - start_x = org_x + random() * delta_x; - start_y = org_y + random() * delta_y; - start_z = org_z + random() * delta_z; + start.x = org.x + random() * delta.x; + start.y = org.y + random() * delta.y; + start.z = org.z + random() * delta.z; - end_x = org_x + random() * delta_x; - end_y = org_y + random() * delta_y; - end_z = org_z + random() * delta_z; + end.x = org.x + random() * delta.x; + end.y = org.y + random() * delta.y; + end.z = org.z + random() * delta.z; start = stov(vtos(start)); end = stov(vtos(end)); tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world); - if(!trace_startsolid) + if(!trace_startsolid && trace_fraction < 1) { p = trace_endpos; tracebox(p, PL_MIN, PL_MAX, p, MOVE_NOMONSTERS, world); - if(trace_startsolid || trace_fraction == 1) + if(trace_startsolid) { rint(42); // do an engine breakpoint on VM_rint so you can get the trace that errnoeously returns startsolid tracebox(start, PL_MIN, PL_MAX, end, MOVE_NOMONSTERS, world); - if(trace_startsolid) + // how much do we need to back off? + safe = 1; + unsafe = 0; + for (;;) { - // how much do we need to back off? - safe = 1; - unsafe = 0; - for(;;) + pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5); + tracebox(pos, PL_MIN, PL_MAX, pos, MOVE_NOMONSTERS, world); + if(trace_startsolid) { - pos = p * (1 - (safe + unsafe) * 0.5) + start * ((safe + unsafe) * 0.5); - tracebox(pos, PL_MIN, PL_MAX, pos, MOVE_NOMONSTERS, world); - if(trace_startsolid) - { - if((safe + unsafe) * 0.5 == unsafe) - break; - unsafe = (safe + unsafe) * 0.5; - } - else - { - if((safe + unsafe) * 0.5 == safe) - break; - safe = (safe + unsafe) * 0.5; - } + if((safe + unsafe) * 0.5 == unsafe) + break; + unsafe = (safe + unsafe) * 0.5; } - - print("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu\n"); - print("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu\n"); - - tracebox(p, PL_MIN + '0.1 0.1 0.1', PL_MAX - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, world); - if(trace_startsolid) - print("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); else - print("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); - break; + { + if((safe + unsafe) * 0.5 == safe) + break; + safe = (safe + unsafe) * 0.5; + } } + print("safe distance to back off: ", ftos(safe * vlen(p - start)), "qu\n"); + print("unsafe distance to back off: ", ftos(unsafe * vlen(p - start)), "qu\n"); + + tracebox(p, PL_MIN + '0.1 0.1 0.1', PL_MAX - '0.1 0.1 0.1', p, MOVE_NOMONSTERS, world); + if(trace_startsolid) + print("trace_endpos much in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); + else + print("trace_endpos just in solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); + if (++hitcount >= 10) + break; + } + else + { q0 = p; dq = 0; dqf = 1; - for(;;) + for (;;) { q = p + normalize(end - p) * (dq + dqf); if(q == q0) @@ -1593,11 +1632,13 @@ void GameCommand_trace(float request, float argc) dqf *= 0.5; q0 = q; } - if(dq > 0) + if(dq > worst_endpos_bug) { + worst_endpos_bug = dq; print("trace_endpos still before solid when tracing from ", vtos(start), " to ", vtos(end), " endpos ", vtos(p), "\n"); print("could go ", ftos(dq), " units further to ", vtos(q), "\n"); - break; + if (++hitcount >= 10) + break; } } } @@ -1619,17 +1660,17 @@ void GameCommand_trace(float request, float argc) for(i = 0; i < 100000; ++i) { dv = randomvec(); - if(dv_z > 0) + if(dv.z > 0) dv = -1 * dv; tracebox(vv, e.mins, e.maxs, vv + dv, MOVE_NORMAL, e); if(trace_startsolid) print("bug 1\n"); if(trace_fraction == 1) - if(dv_z < f) + if(dv.z < f) { - print("bug 2: ", ftos(dv_x), " ", ftos(dv_y), " ", ftos(dv_z)); - print(" (", ftos(asin(dv_z / vlen(dv)) * 180 / M_PI), " degrees)\n"); - f = dv_z; + print("bug 2: ", ftos(dv.x), " ", ftos(dv.y), " ", ftos(dv.z)); + print(" (", ftos(asin(dv.z / vlen(dv)) * 180 / M_PI), " degrees)\n"); + f = dv.z; } } print("highest possible dist: ", ftos(f), "\n"); @@ -1812,7 +1853,7 @@ void GameCommand_macro_help() #define SERVER_COMMAND(name,function,description) \ { print(" ^2", name, "^7: ", description, "\n"); } - SERVER_COMMANDS(0, 0, "") + SERVER_COMMANDS(0, 0, ""); #undef SERVER_COMMAND return; @@ -1821,23 +1862,23 @@ void GameCommand_macro_help() float GameCommand_macro_command(float argc, string command) { #define SERVER_COMMAND(name,function,description) \ - { if(name == strtolower(argv(0))) { function; return TRUE; } } + { if(name == strtolower(argv(0))) { function; return true; } } - SERVER_COMMANDS(CMD_REQUEST_COMMAND, argc, command) + SERVER_COMMANDS(CMD_REQUEST_COMMAND, argc, command); #undef SERVER_COMMAND - return FALSE; + return false; } float GameCommand_macro_usage(float argc) { #define SERVER_COMMAND(name,function,description) \ - { if(name == strtolower(argv(1))) { function; return TRUE; } } + { if(name == strtolower(argv(1))) { function; return true; } } - SERVER_COMMANDS(CMD_REQUEST_USAGE, argc, "") + SERVER_COMMANDS(CMD_REQUEST_USAGE, argc, ""); #undef SERVER_COMMAND - return FALSE; + return false; } void GameCommand_macro_write_aliases(float fh) @@ -1845,7 +1886,7 @@ void GameCommand_macro_write_aliases(float fh) #define SERVER_COMMAND(name,function,description) \ { CMD_Write_Alias("qc_cmd_sv", name, description); } - SERVER_COMMANDS(0, 0, "") + SERVER_COMMANDS(0, 0, ""); #undef SERVER_COMMAND return;