Example #1
0
        /*
         * ============= SV_PointContents =============
         */
        public static int SV_PointContents(float[] p)
        {
            edict_t hit;
            int     i, num;
            int     contents, c2;
            int     headnode;

            // get base contents from world
            contents = CM.PointContents(p, SV_INIT.sv.models[1].headnode);

            // or in contents from all the other entities
            num = SV_WORLD.SV_AreaEdicts(p, p, SV_WORLD.touch, Defines.MAX_EDICTS, Defines.AREA_SOLID);

            for (i = 0; i < num; i++)
            {
                hit = SV_WORLD.touch[i];

                // might intersect, so do an exact clip
                headnode = SV_WORLD.SV_HullForEntity(hit);

                if (hit.solid != Defines.SOLID_BSP)
                {
                }

                c2        = CM.TransformedPointContents(p, headnode, hit.s.origin, hit.s.angles);
                contents |= c2;
            }

            return(contents);
        }
Example #2
0
        /*
         * ==================== SV_AreaEdicts_r
         *
         * ====================
         */
        public static void SV_AreaEdicts_r(areanode_t node)
        {
            link_t  l, next, start;
            edict_t check;

            // touch linked edicts
            if (SV_WORLD.area_type == Defines.AREA_SOLID)
            {
                start = node.solid_edicts;
            }
            else
            {
                start = node.trigger_edicts;
            }

            for (l = start.next; l != start; l = next)
            {
                next  = l.next;
                check = (edict_t)l.o;

                if (check.solid == Defines.SOLID_NOT)
                {
                    continue;                     // deactivated
                }
                if (check.absmin[0] > SV_WORLD.area_maxs[0] ||
                    check.absmin[1] > SV_WORLD.area_maxs[1] ||
                    check.absmin[2] > SV_WORLD.area_maxs[2] ||
                    check.absmax[0] < SV_WORLD.area_mins[0] ||
                    check.absmax[1] < SV_WORLD.area_mins[1] ||
                    check.absmax[2] < SV_WORLD.area_mins[2])
                {
                    continue;                     // not touching
                }
                if (SV_WORLD.area_count == SV_WORLD.area_maxcount)
                {
                    Com.Printf("SV_AreaEdicts: MAXCOUNT\n");

                    return;
                }

                SV_WORLD.area_list[SV_WORLD.area_count] = check;
                SV_WORLD.area_count++;
            }

            if (node.axis == -1)
            {
                return;                 // terminal node
            }
            // recurse down both sides
            if (SV_WORLD.area_maxs[node.axis] > node.dist)
            {
                SV_WORLD.SV_AreaEdicts_r(node.children[0]);
            }

            if (SV_WORLD.area_mins[node.axis] < node.dist)
            {
                SV_WORLD.SV_AreaEdicts_r(node.children[1]);
            }
        }
Example #3
0
 /*
  * =============== SV_UnlinkEdict ===============
  */
 public static void SV_UnlinkEdict(edict_t ent)
 {
     if (null == ent.area.prev)
     {
         return;                 // not linked in anywhere
     }
     SV_WORLD.RemoveLink(ent.area);
     ent.area.prev = ent.area.next = null;
 }
Example #4
0
        /*
         * ================ SV_AreaEdicts ================
         */
        public static int SV_AreaEdicts(float[] mins, float[] maxs, edict_t[] list, int maxcount, int areatype)
        {
            SV_WORLD.area_mins     = mins;
            SV_WORLD.area_maxs     = maxs;
            SV_WORLD.area_list     = list;
            SV_WORLD.area_count    = 0;
            SV_WORLD.area_maxcount = maxcount;
            SV_WORLD.area_type     = areatype;
            SV_WORLD.SV_AreaEdicts_r(SV_WORLD.sv_areanodes[0]);

            return(SV_WORLD.area_count);
        }
Example #5
0
        /**
         * SV_CheckForSavegame.
         */
        public static void SV_CheckForSavegame()
        {
            string name;

            int i;

            if (SV_MAIN.sv_noreload.value != 0)
            {
                return;
            }

            if (Cvar.VariableValue("deathmatch") != 0)
            {
                return;
            }

            name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sav";

            if (!File.Exists(name))
            {
                return;
            }

            SV_WORLD.SV_ClearWorld();

            // get configstrings and areaportals
            SV_CCMDS.SV_ReadLevelFile();

            if (!SV_INIT.sv.loadgame)
            {
                // coming back to a level after being in a different
                // level, so run it for ten seconds

                // rlava2 was sending too many lightstyles, and overflowing the
                // reliable data. temporarily changing the server state to loading
                // prevents these from being passed down.
                int previousState;                     // PGM

                previousState    = SV_INIT.sv.state;   // PGM
                SV_INIT.sv.state = Defines.ss_loading; // PGM

                for (i = 0; i < 100; i++)
                {
                    GameBase.G_RunFrame();
                }

                SV_INIT.sv.state = previousState;                 // PGM
            }
        }
Example #6
0
        /*
         * =============== SV_ClearWorld
         *
         * ===============
         */
        public static void SV_ClearWorld()
        {
            SV_WORLD.initNodes();
            SV_WORLD.sv_numareanodes = 0;
            SV_WORLD.SV_CreateAreaNode(0, SV_INIT.sv.models[1].mins, SV_INIT.sv.models[1].maxs);

            /*
             * Com.p("areanodes:" + sv_numareanodes + " (sollten 32 sein)."); for
             * (int n = 0; n < sv_numareanodes; n++) { Com.Printf( "|%3i|%2i|%8.2f
             * |%8.2f|%8.2f|%8.2f| %8.2f|%8.2f|%8.2f|\n", new Vargs() .add(n)
             * .add(sv_areanodes[n].axis) .add(sv_areanodes[n].dist)
             * .add(sv_areanodes[n].mins_rst[0]) .add(sv_areanodes[n].mins_rst[1])
             * .add(sv_areanodes[n].mins_rst[2]) .add(sv_areanodes[n].maxs_rst[0])
             * .add(sv_areanodes[n].maxs_rst[1]) .add(sv_areanodes[n].maxs_rst[2])); }
             */
        }
Example #7
0
        /*
         * =============== SV_CreateAreaNode
         *
         * Builds a uniformly subdivided tree for the given world size
         * ===============
         */
        public static areanode_t SV_CreateAreaNode(int depth, float[] mins, float[] maxs)
        {
            areanode_t anode;

            float[] size  = { 0, 0, 0 };
            float[] mins1 = { 0, 0, 0 }, maxs1 = { 0, 0, 0 }, mins2 = { 0, 0, 0 }, maxs2 = { 0, 0, 0 };
            anode = SV_WORLD.sv_areanodes[SV_WORLD.sv_numareanodes];

            // just for debugging (rst)
            //        Math3D.VectorCopy(mins, anode.mins_rst);
            //        Math3D.VectorCopy(maxs, anode.maxs_rst);
            SV_WORLD.sv_numareanodes++;
            SV_WORLD.ClearLink(anode.trigger_edicts);
            SV_WORLD.ClearLink(anode.solid_edicts);

            if (depth == Defines.AREA_DEPTH)
            {
                anode.axis        = -1;
                anode.children[0] = anode.children[1] = null;

                return(anode);
            }

            Math3D.VectorSubtract(maxs, mins, size);

            if (size[0] > size[1])
            {
                anode.axis = 0;
            }
            else
            {
                anode.axis = 1;
            }

            anode.dist = 0.5f * (maxs[anode.axis] + mins[anode.axis]);
            Math3D.VectorCopy(mins, mins1);
            Math3D.VectorCopy(mins, mins2);
            Math3D.VectorCopy(maxs, maxs1);
            Math3D.VectorCopy(maxs, maxs2);
            maxs1[anode.axis] = mins2[anode.axis] = anode.dist;
            anode.children[0] = SV_WORLD.SV_CreateAreaNode(depth + 1, mins2, maxs2);
            anode.children[1] = SV_WORLD.SV_CreateAreaNode(depth + 1, mins1, maxs1);

            return(anode);
        }
Example #8
0
        /*
         * ================== SV_Trace
         *
         * Moves the given mins/maxs volume through the world from start to end.
         *
         * Passedict and edicts owned by passedict are explicitly not checked.
         *
         * ==================
         */
        public static trace_t SV_Trace(float[] start, float[] mins, float[] maxs, float[] end, edict_t passedict, int contentmask)
        {
            moveclip_t clip = new();

            if (mins == null)
            {
                mins = Globals.vec3_origin;
            }

            if (maxs == null)
            {
                maxs = Globals.vec3_origin;
            }

            // clip to world
            clip.trace     = CM.BoxTrace(start, end, mins, maxs, 0, contentmask);
            clip.trace.ent = GameBase.g_edicts[0];

            if (clip.trace.fraction == 0)
            {
                return(clip.trace);                // blocked by the world
            }
            clip.contentmask = contentmask;
            clip.start       = start;
            clip.end         = end;
            clip.mins        = mins;
            clip.maxs        = maxs;
            clip.passedict   = passedict;
            Math3D.VectorCopy(mins, clip.mins2);
            Math3D.VectorCopy(maxs, clip.maxs2);

            // create the bounding box of the entire move
            SV_WORLD.SV_TraceBounds(start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs);

            // clip to other solid entities
            SV_WORLD.SV_ClipMoveToEntities(clip);

            return(clip.trace);
        }
Example #9
0
        /**
         * PF_setmodel
         *
         * Also sets mins and maxs for inline bmodels.
         */
        public static void PF_setmodel(edict_t ent, string name)
        {
            int      i;
            cmodel_t mod;

            if (name == null)
            {
                Com.Error(Defines.ERR_DROP, "PF_setmodel: NULL");
            }

            i = SV_INIT.SV_ModelIndex(name);

            ent.s.modelindex = i;

            // if it is an inline model, get the size information for it
            if (name.StartsWith("*"))
            {
                mod = CM.InlineModel(name);
                Math3D.VectorCopy(mod.mins, ent.mins);
                Math3D.VectorCopy(mod.maxs, ent.maxs);
                SV_WORLD.SV_LinkEdict(ent);
            }
        }
Example #10
0
        /**
         * SV_SpawnServer.
         *
         * Change the server to a new map, taking all connected clients along with
         * it.
         */
        public static void SV_SpawnServer(string server, string spawnpoint, int serverstate, bool attractloop, bool loadgame)
        {
            int i;
            var checksum = 0;

            if (attractloop)
            {
                Cvar.Set("paused", "0");
            }

            Com.Printf("------- Server Initialization -------\n");

            Com.DPrintf("SpawnServer: " + server + "\n");

            if (SV_INIT.sv.demofile != null)
            {
                try
                {
                    SV_INIT.sv.demofile.Close();
                }
                catch (Exception)
                {
                }
            }

            // any partially connected client will be restarted
            SV_INIT.svs.spawncount++;

            SV_INIT.sv.state = Defines.ss_dead;

            Globals.server_state = SV_INIT.sv.state;

            // wipe the entire per-level structure
            SV_INIT.sv = new();

            SV_INIT.svs.realtime   = 0;
            SV_INIT.sv.loadgame    = loadgame;
            SV_INIT.sv.attractloop = attractloop;

            // save name for levels that don't set message
            SV_INIT.sv.configstrings[Defines.CS_NAME] = server;

            if (Cvar.VariableValue("deathmatch") != 0)
            {
                SV_INIT.sv.configstrings[Defines.CS_AIRACCEL] = "" + SV_MAIN.sv_airaccelerate.value;
                PMove.pm_airaccelerate = SV_MAIN.sv_airaccelerate.value;
            }
            else
            {
                SV_INIT.sv.configstrings[Defines.CS_AIRACCEL] = "0";
                PMove.pm_airaccelerate = 0;
            }

            SZ.Init(SV_INIT.sv.multicast, SV_INIT.sv.multicast_buf, SV_INIT.sv.multicast_buf.Length);

            SV_INIT.sv.name = server;

            // leave slots at start for clients only
            for (i = 0; i < SV_MAIN.maxclients.value; i++)
            {
                // needs to reconnect
                if (SV_INIT.svs.clients[i].state > Defines.cs_connected)
                {
                    SV_INIT.svs.clients[i].state = Defines.cs_connected;
                }

                SV_INIT.svs.clients[i].lastframe = -1;
            }

            SV_INIT.sv.time = 1000;

            SV_INIT.sv.name = server;
            SV_INIT.sv.configstrings[Defines.CS_NAME] = server;

            int[] iw = { checksum };

            if (serverstate != Defines.ss_game)
            {
                SV_INIT.sv.models[1] = CM.CM_LoadMap("", false, iw);                 // no real map
            }
            else
            {
                SV_INIT.sv.configstrings[Defines.CS_MODELS + 1] = "maps/" + server + ".bsp";
                SV_INIT.sv.models[1] = CM.CM_LoadMap(SV_INIT.sv.configstrings[Defines.CS_MODELS + 1], false, iw);
            }

            checksum = iw[0];
            SV_INIT.sv.configstrings[Defines.CS_MAPCHECKSUM] = "" + checksum;

            // clear physics interaction links

            SV_WORLD.SV_ClearWorld();

            for (i = 1; i < CM.CM_NumInlineModels(); i++)
            {
                SV_INIT.sv.configstrings[Defines.CS_MODELS + 1 + i] = "*" + i;

                // copy references
                SV_INIT.sv.models[i + 1] = CM.InlineModel(SV_INIT.sv.configstrings[Defines.CS_MODELS + 1 + i]);
            }

            // spawn the rest of the entities on the map

            // precache and static commands can be issued during
            // map initialization

            SV_INIT.sv.state     = Defines.ss_loading;
            Globals.server_state = SV_INIT.sv.state;

            // load and spawn all other entities
            GameSpawn.SpawnEntities(SV_INIT.sv.name, CM.CM_EntityString(), spawnpoint);

            // run two frames to allow everything to settle
            GameBase.G_RunFrame();
            GameBase.G_RunFrame();

            // all precaches are complete
            SV_INIT.sv.state     = serverstate;
            Globals.server_state = SV_INIT.sv.state;

            // create a baseline for more efficient communications
            SV_INIT.SV_CreateBaseline();

            // check for a savegame
            SV_INIT.SV_CheckForSavegame();

            // set serverinfo variable
            Cvar.FullSet("mapname", SV_INIT.sv.name, Defines.CVAR_SERVERINFO | Defines.CVAR_NOSET);
        }
Example #11
0
        public static void SV_ClipMoveToEntities(moveclip_t clip)
        {
            int     i, num;
            edict_t touch;
            trace_t trace;
            int     headnode;

            float[] angles;
            num = SV_WORLD.SV_AreaEdicts(clip.boxmins, clip.boxmaxs, SV_WORLD.touchlist, Defines.MAX_EDICTS, Defines.AREA_SOLID);

            // be careful, it is possible to have an entity in this
            // list removed before we get to it (killtriggered)
            for (i = 0; i < num; i++)
            {
                touch = SV_WORLD.touchlist[i];

                if (touch.solid == Defines.SOLID_NOT)
                {
                    continue;
                }

                if (touch == clip.passedict)
                {
                    continue;
                }

                if (clip.trace.allsolid)
                {
                    return;
                }

                if (clip.passedict != null)
                {
                    if (touch.owner == clip.passedict)
                    {
                        continue;                         // don't clip against own missiles
                    }
                    if (clip.passedict.owner == touch)
                    {
                        continue;                         // don't clip against owner
                    }
                }

                if (0 == (clip.contentmask & Defines.CONTENTS_DEADMONSTER) && 0 != (touch.svflags & Defines.SVF_DEADMONSTER))
                {
                    continue;
                }

                // might intersect, so do an exact clip
                headnode = SV_WORLD.SV_HullForEntity(touch);
                angles   = touch.s.angles;

                if (touch.solid != Defines.SOLID_BSP)
                {
                    angles = Globals.vec3_origin;                     // boxes don't rotate
                }
                if ((touch.svflags & Defines.SVF_MONSTER) != 0)
                {
                    trace = CM.TransformedBoxTrace(clip.start, clip.end, clip.mins2, clip.maxs2, headnode, clip.contentmask, touch.s.origin, angles);
                }
                else
                {
                    trace = CM.TransformedBoxTrace(clip.start, clip.end, clip.mins, clip.maxs, headnode, clip.contentmask, touch.s.origin, angles);
                }

                if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction)
                {
                    trace.ent = touch;

                    if (clip.trace.startsolid)
                    {
                        clip.trace            = trace;
                        clip.trace.startsolid = true;
                    }
                    else
                    {
                        clip.trace.set(trace);
                    }
                }
                else if (trace.startsolid)
                {
                    clip.trace.startsolid = true;
                }
            }
        }
Example #12
0
 static SV_WORLD()
 {
     SV_WORLD.initNodes();
 }
Example #13
0
        public static void SV_LinkEdict(edict_t ent)
        {
            areanode_t node;
            int        num_leafs;
            int        j, k;
            int        area;
            var        topnode = 0;

            if (ent.area.prev != null)
            {
                SV_WORLD.SV_UnlinkEdict(ent);                 // unlink from old position
            }
            if (ent == GameBase.g_edicts[0])
            {
                return;                 // don't add the world
            }
            if (!ent.inuse)
            {
                return;
            }

            // set the size
            Math3D.VectorSubtract(ent.maxs, ent.mins, ent.size);

            // encode the size into the entity_state for client prediction
            if (ent.solid == Defines.SOLID_BBOX && 0 == (ent.svflags & Defines.SVF_DEADMONSTER))
            {
                // assume that x/y are equal and symetric
                var i = (int)(ent.maxs[0] / 8);

                if (i < 1)
                {
                    i = 1;
                }

                if (i > 31)
                {
                    i = 31;
                }

                // z is not symetric
                j = (int)(-ent.mins[2] / 8);

                if (j < 1)
                {
                    j = 1;
                }

                if (j > 31)
                {
                    j = 31;
                }

                // and z maxs can be negative...
                k = (int)((ent.maxs[2] + 32) / 8);

                if (k < 1)
                {
                    k = 1;
                }

                if (k > 63)
                {
                    k = 63;
                }

                ent.s.solid = (k << 10) | (j << 5) | i;
            }
            else if (ent.solid == Defines.SOLID_BSP)
            {
                ent.s.solid = 31;                 // a solid_bbox will never create this value
            }
            else
            {
                ent.s.solid = 0;
            }

            // set the abs box
            if (ent.solid == Defines.SOLID_BSP && (ent.s.angles[0] != 0 || ent.s.angles[1] != 0 || ent.s.angles[2] != 0))
            {
                // expand for rotation
                float max, v;
                max = 0;

                for (var i = 0; i < 3; i++)
                {
                    v = Math.Abs(ent.mins[i]);

                    if (v > max)
                    {
                        max = v;
                    }

                    v = Math.Abs(ent.maxs[i]);

                    if (v > max)
                    {
                        max = v;
                    }
                }

                for (var i = 0; i < 3; i++)
                {
                    ent.absmin[i] = ent.s.origin[i] - max;
                    ent.absmax[i] = ent.s.origin[i] + max;
                }
            }
            else
            {
                // normal
                Math3D.VectorAdd(ent.s.origin, ent.mins, ent.absmin);
                Math3D.VectorAdd(ent.s.origin, ent.maxs, ent.absmax);
            }

            // because movement is clipped an epsilon away from an actual edge,
            // we must fully check even when bounding boxes don't quite touch
            ent.absmin[0]--;
            ent.absmin[1]--;
            ent.absmin[2]--;
            ent.absmax[0]++;
            ent.absmax[1]++;
            ent.absmax[2]++;

            // link to PVS leafs
            ent.num_clusters = 0;
            ent.areanum      = 0;
            ent.areanum2     = 0;

            // get all leafs, including solids
            int[] iw = { topnode };
            num_leafs = CM.CM_BoxLeafnums(ent.absmin, ent.absmax, SV_WORLD.leafs, SV_WORLD.MAX_TOTAL_ENT_LEAFS, iw);
            topnode   = iw[0];

            // set areas
            for (var i = 0; i < num_leafs; i++)
            {
                SV_WORLD.clusters[i] = CM.CM_LeafCluster(SV_WORLD.leafs[i]);
                area = CM.CM_LeafArea(SV_WORLD.leafs[i]);

                if (area != 0)
                {
                    // doors may legally straggle two areas,
                    // but nothing should evern need more than that
                    if (ent.areanum != 0 && ent.areanum != area)
                    {
                        if (ent.areanum2 != 0 && ent.areanum2 != area && SV_INIT.sv.state == Defines.ss_loading)
                        {
                            Com.DPrintf("Object touching 3 areas at " + ent.absmin[0] + " " + ent.absmin[1] + " " + ent.absmin[2] + "\n");
                        }

                        ent.areanum2 = area;
                    }
                    else
                    {
                        ent.areanum = area;
                    }
                }
            }

            if (num_leafs >= SV_WORLD.MAX_TOTAL_ENT_LEAFS)
            {
                // assume we missed some leafs, and mark by headnode
                ent.num_clusters = -1;
                ent.headnode     = topnode;
            }
            else
            {
                ent.num_clusters = 0;

                for (var i = 0; i < num_leafs; i++)
                {
                    if (SV_WORLD.clusters[i] == -1)
                    {
                        continue;                         // not a visible leaf
                    }
                    for (j = 0; j < i; j++)
                    {
                        if (SV_WORLD.clusters[j] == SV_WORLD.clusters[i])
                        {
                            break;
                        }
                    }

                    if (j == i)
                    {
                        if (ent.num_clusters == Defines.MAX_ENT_CLUSTERS)
                        {
                            // assume we missed some leafs, and mark by headnode
                            ent.num_clusters = -1;
                            ent.headnode     = topnode;

                            break;
                        }

                        ent.clusternums[ent.num_clusters++] = SV_WORLD.clusters[i];
                    }
                }
            }

            // if first time, make sure old_origin is valid
            if (0 == ent.linkcount)
            {
                Math3D.VectorCopy(ent.s.origin, ent.s.old_origin);
            }

            ent.linkcount++;

            if (ent.solid == Defines.SOLID_NOT)
            {
                return;
            }

            // find the first node that the ent's box crosses
            node = SV_WORLD.sv_areanodes[0];

            while (true)
            {
                if (node.axis == -1)
                {
                    break;
                }

                if (ent.absmin[node.axis] > node.dist)
                {
                    node = node.children[0];
                }
                else if (ent.absmax[node.axis] < node.dist)
                {
                    node = node.children[1];
                }
                else
                {
                    break;                     // crosses the node
                }
            }

            // link it in
            if (ent.solid == Defines.SOLID_TRIGGER)
            {
                SV_WORLD.InsertLinkBefore(ent.area, node.trigger_edicts);
            }
            else
            {
                SV_WORLD.InsertLinkBefore(ent.area, node.solid_edicts);
            }
        }