void AddEntToSnapshot(svEntity_t svEnt, sharedEntity gEnt, List<int> eNums) { // if we have already added this entity to this snapshot, don't add again if (svEnt.snapshotCounter == sv.snapshotCounter) return; svEnt.snapshotCounter = sv.snapshotCounter; // if we are full, silently discard entities if (eNums.Count > 1024) { Common.Instance.WriteLine("Snapshot is full"); return; } eNums.Add(gEnt.s.number); }
public gentity_t() { shEnt = new sharedEntity(); }
int ClipHandleForEntity(sharedEntity ent) { return ClipMap.Instance.TempBoxModel(ent.r.mins, ent.r.maxs); }
public Server.svEntity_t SvEntityForGentity(sharedEntity gEnt) { if (gEnt == null || gEnt.s.number < 0 || gEnt.s.number >= 1024) Common.Instance.Error("SvEntityForGentity: Bad gEnt"); return Server.Instance.sv.svEntities[gEnt.s.number]; }
public void UnlinkEntity(sharedEntity gEnt) { svEntity_t ent = Game.Instance.SvEntityForGentity(gEnt); gEnt.r.linked = false; worldSector_t ws = ent.worldSector; if (ws == null) return; // not linked in anywhere ent.worldSector = null; if (ws.entities == ent) { ws.entities = ent.nextEntityInWorldSector; return; } svEntity_t scan; for (scan = ent; scan != null; scan = scan.nextEntityInWorldSector) { if (scan.nextEntityInWorldSector == ent) { scan.nextEntityInWorldSector = ent.nextEntityInWorldSector; return; } } Common.Instance.WriteLine("Warning: SV_UnlinkEntity: not found in worldsector"); }
public void LocateGameData(sharedEntity[] gEnts, int entityCount, gclient_t[] clients) { sv.gentities = gEnts; //sv.gentities = new List<sharedEntity>(); //for (int i = 0; i < gEnts.Count; i++) //{ // sv.gentities.Add(Game.Instance.GEntityToSharedEntity(gEnts[i])); //} sv.num_entities = entityCount; sv.gameClients = clients; }
public void LinkEntity(sharedEntity gEnt) { svEntity_t ent = sv.svEntities[gEnt.s.number]; if (ent.worldSector != null) { UnlinkEntity(gEnt); } // encode the size into the entityState_t for client prediction if (gEnt.r.bmodel) { gEnt.s.solid = 0xffffff; // SOLID_BMODEL } else if ((gEnt.r.contents & (int)(brushflags.CONTENTS_SOLID | brushflags.CONTENTS_MONSTER)) > 0) { // assume that x/y are equal and symetric int i = (int)gEnt.r.maxs[0]; if (i < 1) i = 1; if (i > 255) i = 255; int j = (int)-gEnt.r.mins[2]; if (j < 1) j = 1; if (j > 255) j = 255; int k = (int)gEnt.r.maxs[2] + 32; if (k < 1) k = 1; if (k > 255) k = 255; gEnt.s.solid = (k << 16) | (j << 8) | i; } else { gEnt.s.solid = 0; } // set the abs box if (gEnt.r.bmodel && (gEnt.r.currentAngles[0] != 0 || gEnt.r.currentAngles[1] != 0 || gEnt.r.currentAngles[2] != 0)) { // expand for rotation float max = RadiusFromBounds(gEnt.r.mins, gEnt.r.maxs); for (int i = 0; i < 3; i++) { gEnt.r.absmin[i] = gEnt.r.currentOrigin[i] - max; gEnt.r.absmax[i] = gEnt.r.currentOrigin[i] + max; } } else { // normal gEnt.r.absmin = Vector3.Add(gEnt.r.currentOrigin, gEnt.r.mins); gEnt.r.absmax = Vector3.Add(gEnt.r.currentOrigin, gEnt.r.maxs); } // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch gEnt.r.absmin[0] -= 1; gEnt.r.absmin[1] -= 1; gEnt.r.absmin[2] -= 1; gEnt.r.absmax[0] += 1; gEnt.r.absmax[1] += 1; gEnt.r.absmax[2] += 1; // link to PVS leafs ent.numClusters = 0; ent.lastCluster = 0; ent.areanum = -1; ent.areanum2 = -1; //get all leafs, including solids ClipMap.leafList_t ll = new ClipMap.leafList_t(); ll.lastLeaf = -1; ll.bounds = new Vector3[2]; ll.maxcount = 128; ll.bounds[0] = gEnt.r.absmin; ll.bounds[1] = gEnt.r.absmax; ll.list = new int[128]; ClipMap.Instance.BoxLeafnums(ll, 0); // if none of the leafs were inside the map, the // entity is outside the world and can be considered unlinked if (ll.count <= 0) return; // set areas, even from clusters that don't fit in the entity array for (int i = 0; i < ll.count; i++) { int area = ClipMap.Instance.LeafArea(ll.list[i]); if (area != -1) { // doors may legally straggle two areas, // but nothing should evern need more than that if (ent.areanum != -1 && ent.areanum != area) { if (ent.areanum2 != -1 && ent.areanum2 != area && sv.state == serverState_t.SS_LOADING) { Common.Instance.WriteLine("Object {0} touching 3 areas at {1}", gEnt.s.number, gEnt.r.absmin); } ent.areanum2 = area; } } else { ent.areanum = area; } } // store as many explicit clusters as we can ent.numClusters = 0; int actual = 0; for (int i = 0; i < ll.count; i++) { actual = i; int cluster = ClipMap.Instance.LeafCluster(ll.list[i]); if (cluster != -1) { ent.clusternums[ent.numClusters++] = cluster; if (ent.numClusters == 16) break; } } // store off a last cluster if we need to if (actual != ll.count && ll.lastLeaf != -1) ent.lastCluster = ClipMap.Instance.LeafCluster(ll.lastLeaf); gEnt.r.linkcount++; // find the first world sector node that the ent's box crosses worldSector_t node = sv_worldSectors[0]; while (true) { if (node.axis == -1) break; if (gEnt.r.absmin[node.axis] > node.dist) node = node.children[0]; else if (gEnt.r.absmax[node.axis] < node.dist) node = node.children[1]; else break; // crosses the node } // link it in ent.worldSector = node; ent.nextEntityInWorldSector = node.entities; node.entities = ent; // find the first world sector node that the ent's box crosses gEnt.r.linked = true; }