X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_world.qc;h=8e8dce9b12080abd58a7ff9ac91fd9bd2de9f317;hp=f2eb1d1186eb59f793c503e97f2333f23a5a5589;hb=3bbcff2475d1b2efc1314a358bf60c6fba6e4be6;hpb=1237e104131b37576287fddcbee29a0fe8806f9c diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index f2eb1d1186..8e8dce9b12 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -2,10 +2,10 @@ #include "anticheat.qh" #include "antilag.qh" -#include "bot/bot.qh" +#include "bot/api.qh" #include "campaign.qh" #include "cheats.qh" -#include "cl_client.qh" +#include "client.qh" #include "command/common.qh" #include "command/getreplies.qh" #include "command/sv_cmd.qh" @@ -13,7 +13,7 @@ #include "g_hook.qh" #include "ipban.qh" #include "mapvoting.qh" -#include "mutators/all.qh" +#include "mutators/_mod.qh" #include "race.qh" #include "scores.qh" #include "teamplay.qh" @@ -21,7 +21,7 @@ #include "../common/constants.qh" #include "../common/deathtypes/all.qh" #include "../common/mapinfo.qh" -#include "../common/monsters/all.qh" +#include "../common/monsters/_mod.qh" #include "../common/monsters/sv_monsters.qh" #include "../common/vehicles/all.qh" #include "../common/notifications/all.qh" @@ -32,8 +32,8 @@ #include "../common/triggers/trigger/secret.qh" #include "../common/triggers/target/music.qh" #include "../common/util.qh" -#include "../common/items/all.qh" -#include "../common/weapons/all.qh" +#include "../common/items/_mod.qh" +#include #include "../common/state.qh" const float LATENCY_THINKRATE = 10; @@ -56,9 +56,9 @@ void PingPLReport_Think(entity this) { WriteHeader(MSG_BROADCAST, TE_CSQC_PINGPLREPORT); WriteByte(MSG_BROADCAST, this.cnt); - WriteShort(MSG_BROADCAST, max(1, e.ping)); - WriteByte(MSG_BROADCAST, ceil(e.ping_packetloss * 255)); - WriteByte(MSG_BROADCAST, ceil(e.ping_movementloss * 255)); + WriteShort(MSG_BROADCAST, bound(1, e.ping, 65535)); + WriteByte(MSG_BROADCAST, min(ceil(e.ping_packetloss * 255), 255)); + WriteByte(MSG_BROADCAST, min(ceil(e.ping_movementloss * 255), 255)); // record latency times for clients throughout the match so we can report it to playerstats if(time > (e.latency_time + LATENCY_THINKRATE)) @@ -320,17 +320,20 @@ void cvar_changes_init() BADCVAR("g_invasion_point_limit"); BADCVAR("g_keyhunt_point_leadlimit"); BADCVAR("g_nexball_goalleadlimit"); + BADCVAR("g_new_toys_use_pickupsound"); + BADCVAR("g_physics_predictall"); + BADCVAR("g_piggyback"); BADCVAR("g_tdm_point_leadlimit"); BADCVAR("g_tdm_point_limit"); BADCVAR("leadlimit_and_fraglimit"); BADCVAR("leadlimit_override"); BADCVAR("pausable"); - BADCVAR("sv_allow_fullbright"); BADCVAR("sv_checkforpacketsduringsleep"); BADCVAR("sv_intermission_cdtrack"); BADCVAR("sv_minigames"); BADCVAR("sv_namechangetimer"); BADCVAR("sv_precacheplayermodels"); + BADCVAR("sv_stepheight"); BADCVAR("sv_timeout"); BADPREFIX("crypto_"); BADPREFIX("gameversion_"); @@ -342,9 +345,11 @@ void cvar_changes_init() BADPREFIX("net_"); BADPREFIX("prvm_"); BADPREFIX("skill_"); + BADPREFIX("sv_allow_"); BADPREFIX("sv_cullentities_"); BADPREFIX("sv_maxidle_"); BADPREFIX("sv_minigames_"); + BADPREFIX("sv_radio_"); BADPREFIX("sv_timeout_"); BADPREFIX("sv_vote_"); BADPREFIX("timelimit_"); @@ -369,6 +374,7 @@ void cvar_changes_init() BADCVAR("g_balance_teams_scorefactor"); BADCVAR("g_ban_sync_trusted_servers"); BADCVAR("g_ban_sync_uri"); + BADCVAR("g_buffs"); BADCVAR("g_ca_teams_override"); BADCVAR("g_ctf_ignore_frags"); BADCVAR("g_domination_point_limit"); @@ -391,6 +397,8 @@ void cvar_changes_init() BADCVAR("g_maxplayers"); BADCVAR("g_mirrordamage"); BADCVAR("g_nexball_goallimit"); + BADCVAR("g_norecoil"); + BADCVAR("g_physics_clientselect"); BADCVAR("g_powerups"); BADCVAR("g_spawnshieldtime"); BADCVAR("g_start_delay"); @@ -443,6 +451,7 @@ void cvar_changes_init() BADCVAR("g_grappling_hook"); BADCVAR("g_jetpack"); +#undef BADPRESUFFIX #undef BADPREFIX #undef BADCVAR @@ -540,7 +549,7 @@ spawnfunc(__init_dedicated_server) cvar_string = cvar_string_normal; cvar_set = cvar_set_normal; - remove = remove_unsafely; + delete_fn = remove_unsafely; entity e = spawn(); setthink(e, GotoFirstMap); @@ -555,6 +564,8 @@ spawnfunc(__init_dedicated_server) static_init_late(); static_init_precache(); + IL_PUSH(g_spawnpoints, e); // just incase + MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0); } @@ -646,9 +657,6 @@ spawnfunc(worldspawn) } } - float fd, l; - string s; - cvar = cvar_normal; cvar_string = cvar_string_normal; cvar_set = cvar_set_normal; @@ -657,12 +665,10 @@ spawnfunc(worldspawn) error("world already spawned - you may have EXACTLY ONE worldspawn!"); world_already_spawned = true; - remove = remove_safely; // during spawning, watch what you remove! + delete_fn = remove_safely; // during spawning, watch what you remove! cvar_changes_init(); // do this very early now so it REALLY matches the server config - compressShortVector_init(); - maxclients = 0; for (entity head = nextent(NULL); head; head = nextent(head)) { @@ -753,7 +759,7 @@ spawnfunc(worldspawn) // character set: ASCII 33-126 without the following characters: : ; ' " \ $ if(autocvar_sv_eventlog) { - s = sprintf("%d.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000)); + string s = sprintf("%d.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000)); matchid = strzone(s); GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s)); @@ -806,12 +812,13 @@ spawnfunc(worldspawn) if(whichpack(strcat("maps/", mapname, ".cfg")) != "") { - fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ); + int fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ); if(fd != -1) { + string s; while((s = fgets(fd))) { - l = tokenize_console(s); + int l = tokenize_console(s); if(l < 2) continue; if(argv(0) == "cd") @@ -853,7 +860,7 @@ spawnfunc(worldspawn) monsterlist_reply = strzone(getmonsterlist()); for(int i = 0; i < 10; ++i) { - s = getrecords(i); + string s = getrecords(i); if (s) records_reply[i] = strzone(s); } @@ -872,7 +879,7 @@ spawnfunc(worldspawn) // fill sv_curl_serverpackages from .serverpackage files if (autocvar_sv_curl_serverpackages_auto) { - s = "csprogs-" WATERMARK ".txt"; + string s = "csprogs-" WATERMARK ".txt"; // remove automatically managed files from the list to prevent duplicates for (int i = 0, n = tokenize_console(cvar_string("sv_curl_serverpackages")); i < n; ++i) { @@ -884,7 +891,7 @@ spawnfunc(worldspawn) } // add automatically managed files to the list #define X(match) MACRO_BEGIN { \ - fd = search_begin(match, true, false); \ + int fd = search_begin(match, true, false); \ if (fd >= 0) \ { \ for (int i = 0, j = search_getsize(fd); i < j; ++i) \ @@ -910,7 +917,8 @@ spawnfunc(worldspawn) if(cvar_string("g_mod_config") != cvar_defstring("g_mod_config")) modname = cvar_string("g_mod_config"); // extra mutators that deserve to count as mod - MUTATOR_CALLHOOK(SetModname); + MUTATOR_CALLHOOK(SetModname, modname); + modname = M_ARGV(0, string); // save it for later modname = strzone(modname); @@ -923,7 +931,7 @@ spawnfunc(worldspawn) spawnfunc(light) { //makestatic (this); // Who the f___ did that? - remove(this); + delete(this); } string GetGametype() @@ -970,10 +978,10 @@ float MapHasRightSize(string map) LOG_TRACE("checkwp "); LOG_TRACE(map); if(!fexists(strcat("maps/", map, ".waypoints"))) { - LOG_TRACE(": no waypoints\n"); + LOG_TRACE(": no waypoints"); return false; } - LOG_TRACE(": has waypoints\n"); + LOG_TRACE(": has waypoints"); } // open map size restriction file @@ -988,18 +996,18 @@ float MapHasRightSize(string map) fclose(fh); if(player_count < mapmin) { - LOG_TRACE("not enough\n"); + LOG_TRACE("not enough"); return false; } if(player_count > mapmax) { - LOG_TRACE("too many\n"); + LOG_TRACE("too many"); return false; } - LOG_TRACE("right size\n"); + LOG_TRACE("right size"); return true; } - LOG_TRACE(": not found\n"); + LOG_TRACE(": not found"); return true; } @@ -1038,7 +1046,7 @@ float Map_Check(float position, float pass) return 0; } else - LOG_DEBUG( "Couldn't select '", filename, "'...\n" ); + LOG_DEBUG( "Couldn't select '", filename, "'..." ); return 0; } @@ -1071,7 +1079,7 @@ float() MaplistMethod_Iterate = // usual method { float pass, i; - LOG_TRACE("Trying MaplistMethod_Iterate\n"); + LOG_TRACE("Trying MaplistMethod_Iterate"); for(pass = 1; pass <= 2; ++pass) { @@ -1088,7 +1096,7 @@ float() MaplistMethod_Iterate = // usual method float() MaplistMethod_Repeat = // fallback method { - LOG_TRACE("Trying MaplistMethod_Repeat\n"); + LOG_TRACE("Trying MaplistMethod_Repeat"); if(Map_Check(Map_Current, 2)) return Map_Current; @@ -1099,7 +1107,7 @@ float() MaplistMethod_Random = // random map selection { float i, imax; - LOG_TRACE("Trying MaplistMethod_Random\n"); + LOG_TRACE("Trying MaplistMethod_Random"); imax = 42; @@ -1119,7 +1127,7 @@ float(float exponent) MaplistMethod_Shuffle = // more clever shuffling { float i, j, imax, insertpos; - LOG_TRACE("Trying MaplistMethod_Shuffle\n"); + LOG_TRACE("Trying MaplistMethod_Shuffle"); imax = 42; @@ -1131,7 +1139,7 @@ float(float exponent) MaplistMethod_Shuffle = // more clever shuffling insertpos = pow(random(), 1 / exponent); // ]0, 1] insertpos = insertpos * (Map_Count - 1); // ]0, Map_Count - 1] insertpos = ceil(insertpos) + 1; // {2, 3, 4, ..., Map_Count} - LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos), "\n"); + LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos)); // insert the current map there newlist = ""; @@ -1336,32 +1344,32 @@ entity FindIntermission() local float cyc; // look for info_intermission first - spot = find (NULL, classname, "info_intermission"); + spot = find(NULL, classname, "info_intermission"); if (spot) { // pick a random one cyc = random() * 4; while (cyc > 1) { - spot = find (spot, classname, "info_intermission"); + spot = find(spot, classname, "info_intermission"); if (!spot) - spot = find (spot, classname, "info_intermission"); + spot = find(spot, classname, "info_intermission"); cyc = cyc - 1; } return spot; } // then look for the start position - spot = find (NULL, classname, "info_player_start"); + spot = find(NULL, classname, "info_player_start"); if (spot) return spot; // testinfo_player_start is only found in regioned levels - spot = find (NULL, classname, "testplayerstart"); + spot = find(NULL, classname, "testplayerstart"); if (spot) return spot; // then look for the start position - spot = find (NULL, classname, "info_player_deathmatch"); + spot = find(NULL, classname, "info_player_deathmatch"); if (spot) return spot; @@ -1488,7 +1496,7 @@ void FixIntermissionClient(entity e) e.health = -2342; // first intermission phase; voting phase has positive health (used to decide whether to send SVC_FINALE or not) e.solid = SOLID_NOT; - e.movetype = MOVETYPE_NONE; + set_movetype(e, MOVETYPE_NONE); e.takedamage = DAMAGE_NO; for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { @@ -1505,7 +1513,7 @@ void FixIntermissionClient(entity e) stuffcmd(e, "\nscr_printspeed 1000000\n"); RandomSelection_Init(); FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, LAMBDA( - RandomSelection_Add(NULL, 0, it, 1, 1); + RandomSelection_AddString(it, 1, 1); )); if (RandomSelection_chosen_string != "") { @@ -1772,7 +1780,8 @@ float WinningCondition_RanOutOfSpawns() } )); - FOREACH_ENTITY_CLASS("info_player_deathmatch", true, LAMBDA( + IL_EACH(g_spawnpoints, true, + { switch(it.team) { case NUM_TEAM_1: team1_score = 1; break; @@ -1780,7 +1789,7 @@ float WinningCondition_RanOutOfSpawns() case NUM_TEAM_3: team3_score = 1; break; case NUM_TEAM_4: team4_score = 1; break; } - )); + }); ClearWinners(); if(team1_score + team2_score + team3_score + team4_score == 0) @@ -1984,11 +1993,80 @@ string GotoMap(string m) return "Map switch will happen after scoreboard."; } +bool autocvar_sv_gameplayfix_multiplethinksperframe; +void RunThink(entity this) +{ + // don't let things stay in the past. + // it is possible to start that way by a trigger with a local time. + if(this.nextthink <= 0 || this.nextthink > time + frametime) + return; + + float oldtime = time; // do we need to save this? + + for (int iterations = 0; iterations < 128 && !wasfreed(this); iterations++) + { + time = max(oldtime, this.nextthink); + this.nextthink = 0; + + if(getthink(this)) + getthink(this)(this); + // mods often set nextthink to time to cause a think every frame, + // we don't want to loop in that case, so exit if the new nextthink is + // <= the time the qc was told, also exit if it is past the end of the + // frame + if(this.nextthink <= time || this.nextthink > oldtime + frametime || !autocvar_sv_gameplayfix_multiplethinksperframe) + break; + } + + time = oldtime; +} + +bool autocvar_sv_freezenonclients; +bool autocvar_sv_gameplayfix_delayprojectiles; +void Physics_Frame() +{ + if(autocvar_sv_freezenonclients) + return; + + FOREACH_ENTITY_FLOAT(pure_data, false, + { + if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH || it.move_movetype == MOVETYPE_PHYSICS) + continue; + + set_movetype(it, it.move_movetype); + + if(it.move_movetype == MOVETYPE_NONE) + continue; + + if(it.move_qcphysics) + Movetype_Physics_NoMatchTicrate(it, PHYS_INPUT_TIMELENGTH, false); + + if(it.movetype >= MOVETYPE_USER_FIRST && it.movetype <= MOVETYPE_USER_LAST) // these cases have no think handling + { + // handle thinking here + if (getthink(it) && it.nextthink > 0 && it.nextthink <= time + frametime) + RunThink(it); + } + }); + if(autocvar_sv_gameplayfix_delayprojectiles >= 0) + return; + + FOREACH_ENTITY_FLOAT(move_qcphysics, true, + { + if(IS_CLIENT(it) || is_pure(it) || it.classname == "" || it.move_movetype == MOVETYPE_NONE) + continue; + Movetype_Physics_NoMatchTicrate(it, PHYS_INPUT_TIMELENGTH, false); + }); +} + +void systems_update(); void EndFrame() { anticheat_endframe(); + Physics_Frame(); + FOREACH_CLIENT(IS_REAL_CLIENT(it), { entity e = IS_SPEC(it) ? it.enemy : it; if (e.typehitsound) { @@ -2009,13 +2087,12 @@ void EndFrame() it.damage_dealt = 0; antilag_record(it, CS(it), altime); }); - FOREACH_ENTITY_FLAGS(flags, FL_MONSTER, { + IL_EACH(g_monsters, true, + { antilag_record(it, it, altime); }); - FOREACH_CLIENT(PS(it), { - PlayerState s = PS(it); - s.ps_push(s, it); - }); + systems_update(); + IL_ENDFRAME(); } @@ -2091,7 +2168,7 @@ void Shutdown() if(world_initialized > 0) { world_initialized = 0; - LOG_TRACE("Saving persistent data...\n"); + LOG_TRACE("Saving persistent data..."); Ban_SaveBans(); // playerstats with unfinished match @@ -2114,7 +2191,7 @@ void Shutdown() CheatShutdown(); // must be after cheatcount check db_close(ServerProgsDB); db_close(TemporaryDB); - LOG_TRACE("Saving persistent data... done!\n"); + LOG_TRACE("Saving persistent data... done!"); // tell the bot system the game is ending now bot_endgame();