]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_world.qc
Merge branch 'master' into TimePath/modules
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_world.qc
index 5102aecdf69e6ff2dd931611274a2630db91897a..5b63aa4e0c99c3e52389d6c6bf9ae1826895aa8f 100644 (file)
@@ -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"
@@ -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 <common/weapons/_all.qh>
 #include "../common/state.qh"
 
 const float LATENCY_THINKRATE = 10;
@@ -646,9 +646,6 @@ spawnfunc(worldspawn)
                }
        }
 
-       float fd, l;
-       string s;
-
        cvar = cvar_normal;
        cvar_string = cvar_string_normal;
        cvar_set = cvar_set_normal;
@@ -661,8 +658,6 @@ spawnfunc(worldspawn)
 
        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 +748,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 +801,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 +849,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 +868,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 +880,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) \
@@ -923,7 +919,7 @@ spawnfunc(worldspawn)
 spawnfunc(light)
 {
        //makestatic (this); // Who the f___ did that?
-       remove(this);
+       delete(this);
 }
 
 string GetGametype()
@@ -970,10 +966,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 +984,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 +1034,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 +1067,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 +1084,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 +1095,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 +1115,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 +1127,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 = "";
@@ -1984,6 +1980,34 @@ 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()
@@ -1993,7 +2017,7 @@ void Physics_Frame()
 
        FOREACH_ENTITY_FLOAT(pure_data, false,
        {
-               if(IS_CLIENT(it) || it.classname == "" || it.movetype == MOVETYPE_PUSH || it.movetype == MOVETYPE_FAKEPUSH || it.movetype == MOVETYPE_PHYSICS)
+               if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH || it.move_movetype == MOVETYPE_PHYSICS)
                        continue;
 
                int mt = it.move_movetype;
@@ -2001,17 +2025,24 @@ void Physics_Frame()
                if(mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH || mt == MOVETYPE_PHYSICS)
                {
                        it.move_qcphysics = false;
-                       it.movetype = mt;
+                       set_movetype(it, mt);
                        continue;
                }
-               
-               it.movetype = ((it.move_qcphysics) ? MOVETYPE_NONE : it.move_movetype);
+
+               set_movetype(it, ((it.move_qcphysics) ? MOVETYPE_NONE : 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)
@@ -2025,6 +2056,7 @@ void Physics_Frame()
        });
 }
 
+void systems_update();
 void EndFrame()
 {
        anticheat_endframe();
@@ -2059,6 +2091,7 @@ void EndFrame()
                PlayerState s = PS(it);
                s.ps_push(s, it);
        });
+       systems_update();
        IL_ENDFRAME();
 }
 
@@ -2135,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
@@ -2158,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();