📄 sv_ents.java
字号:
for (i = 0; i < Defines.MAX_STATS; i++) if (ps.stats[i] != ops.stats[i]) statbits |= 1 << i; MSG.WriteLong(msg, statbits); for (i = 0; i < Defines.MAX_STATS; i++) if ((statbits & (1 << i)) != 0) MSG.WriteShort(msg, ps.stats[i]); } /** * Writes a frame to a client system. */ public static void SV_WriteFrameToClient(client_t client, sizebuf_t msg) { //ptr client_frame_t frame, oldframe; int lastframe; //Com.Printf ("%i . %i\n", new // Vargs().add(client.lastframe).add(sv.framenum)); // this is the frame we are creating frame = client.frames[SV_INIT.sv.framenum & Defines.UPDATE_MASK]; if (client.lastframe <= 0) { // client is asking for a retransmit oldframe = null; lastframe = -1; } else if (SV_INIT.sv.framenum - client.lastframe >= (Defines.UPDATE_BACKUP - 3)) { // client hasn't gotten a good message through in a long time // Com_Printf ("%s: Delta request from out-of-date packet.\n", // client.name); oldframe = null; lastframe = -1; } else { // we have a valid message to delta from oldframe = client.frames[client.lastframe & Defines.UPDATE_MASK]; lastframe = client.lastframe; } MSG.WriteByte(msg, Defines.svc_frame); MSG.WriteLong(msg, SV_INIT.sv.framenum); MSG.WriteLong(msg, lastframe); // what we are delta'ing from MSG.WriteByte(msg, client.surpressCount); // rate dropped packets client.surpressCount = 0; // send over the areabits MSG.WriteByte(msg, frame.areabytes); SZ.Write(msg, frame.areabits, frame.areabytes); // delta encode the playerstate SV_WritePlayerstateToClient(oldframe, frame, msg); // delta encode the entities SV_EmitPacketEntities(oldframe, frame, msg); } /** * The client will interpolate the view position, so we can't use a single * PVS point. */ public static void SV_FatPVS(float[] org) { int leafs[] = new int[64]; int i, j, count; int longs; byte src[]; float[] mins = { 0, 0, 0 }, maxs = { 0, 0, 0 }; for (i = 0; i < 3; i++) { mins[i] = org[i] - 8; maxs[i] = org[i] + 8; } count = CM.CM_BoxLeafnums(mins, maxs, leafs, 64, null); if (count < 1) Com.Error(Defines.ERR_FATAL, "SV_FatPVS: count < 1"); longs = (CM.CM_NumClusters() + 31) >> 5; // convert leafs to clusters for (i = 0; i < count; i++) leafs[i] = CM.CM_LeafCluster(leafs[i]); System.arraycopy(CM.CM_ClusterPVS(leafs[0]), 0, SV_ENTS.fatpvs, 0, longs << 2); // or in all the other leaf bits for (i = 1; i < count; i++) { for (j = 0; j < i; j++) if (leafs[i] == leafs[j]) break; if (j != i) continue; // already have the cluster we want src = CM.CM_ClusterPVS(leafs[i]); //for (j=0 ; j<longs ; j++) // ((long *)fatpvs)[j] |= ((long *)src)[j]; int k = 0; for (j = 0; j < longs; j++) { SV_ENTS.fatpvs[k] |= src[k++]; SV_ENTS.fatpvs[k] |= src[k++]; SV_ENTS.fatpvs[k] |= src[k++]; SV_ENTS.fatpvs[k] |= src[k++]; } } } /** * Decides which entities are going to be visible to the client, and copies * off the playerstat and areabits. */ public static void SV_BuildClientFrame(client_t client) { int e, i; float[] org = { 0, 0, 0 }; edict_t ent; edict_t clent; client_frame_t frame; entity_state_t state; int l; int clientarea, clientcluster; int leafnum; int c_fullsend; byte clientphs[]; byte bitvector[]; clent = client.edict; if (clent.client == null) return; // not in game yet // this is the frame we are creating frame = client.frames[SV_INIT.sv.framenum & Defines.UPDATE_MASK]; frame.senttime = SV_INIT.svs.realtime; // save it for ping calc later // find the client's PVS for (i = 0; i < 3; i++) org[i] = clent.client.ps.pmove.origin[i] * 0.125f + clent.client.ps.viewoffset[i]; leafnum = CM.CM_PointLeafnum(org); clientarea = CM.CM_LeafArea(leafnum); clientcluster = CM.CM_LeafCluster(leafnum); // calculate the visible areas frame.areabytes = CM.CM_WriteAreaBits(frame.areabits, clientarea); // grab the current player_state_t frame.ps.set(clent.client.ps); SV_FatPVS(org); clientphs = CM.CM_ClusterPHS(clientcluster); // build up the list of visible entities frame.num_entities = 0; frame.first_entity = SV_INIT.svs.next_client_entities; c_fullsend = 0; for (e = 1; e < GameBase.num_edicts; e++) { ent = GameBase.g_edicts[e]; // ignore ents without visible models if ((ent.svflags & Defines.SVF_NOCLIENT) != 0) continue; // ignore ents without visible models unless they have an effect if (0 == ent.s.modelindex && 0 == ent.s.effects && 0 == ent.s.sound && 0 == ent.s.event) continue; // ignore if not touching a PV leaf // check area if (ent != clent) { if (!CM.CM_AreasConnected(clientarea, ent.areanum)) { // doors can legally straddle two areas, so we may need to check another one if (0 == ent.areanum2 || !CM.CM_AreasConnected(clientarea, ent.areanum2)) continue; // blocked by a door } // beams just check one point for PHS if ((ent.s.renderfx & Defines.RF_BEAM) != 0) { l = ent.clusternums[0]; if (0 == (clientphs[l >> 3] & (1 << (l & 7)))) continue; } else { // FIXME: if an ent has a model and a sound, but isn't // in the PVS, only the PHS, clear the model if (ent.s.sound == 0) { bitvector = SV_ENTS.fatpvs; //clientphs; } else bitvector = SV_ENTS.fatpvs; if (ent.num_clusters == -1) { // too many leafs for // individual check, go by // headnode if (!CM.CM_HeadnodeVisible(ent.headnode, bitvector)) continue; c_fullsend++; } else { // check individual leafs for (i = 0; i < ent.num_clusters; i++) { l = ent.clusternums[i]; if ((bitvector[l >> 3] & (1 << (l & 7))) != 0) break; } if (i == ent.num_clusters) continue; // not visible } if (ent.s.modelindex == 0) { // don't send sounds if they // will be attenuated away float[] delta = { 0, 0, 0 }; float len; Math3D.VectorSubtract(org, ent.s.origin, delta); len = Math3D.VectorLength(delta); if (len > 400) continue; } } } // add it to the circular client_entities array int ix = SV_INIT.svs.next_client_entities % SV_INIT.svs.num_client_entities; state = SV_INIT.svs.client_entities[ix]; if (ent.s.number != e) { Com.DPrintf("FIXING ENT.S.NUMBER!!!\n"); ent.s.number = e; } //*state = ent.s; SV_INIT.svs.client_entities[ix].set(ent.s); // don't mark players missiles as solid if (ent.owner == client.edict) state.solid = 0; SV_INIT.svs.next_client_entities++; frame.num_entities++; } } /** * Save everything in the world out without deltas. Used for recording * footage for merged or assembled demos. */ public static void SV_RecordDemoMessage() { int e; edict_t ent; entity_state_t nostate = new entity_state_t(null); sizebuf_t buf = new sizebuf_t(); byte buf_data[] = new byte[32768]; int len; if (SV_INIT.svs.demofile == null) return; //memset (nostate, 0, sizeof(nostate)); SZ.Init(buf, buf_data, buf_data.length); // write a frame message that doesn't contain a player_state_t MSG.WriteByte(buf, Defines.svc_frame); MSG.WriteLong(buf, SV_INIT.sv.framenum); MSG.WriteByte(buf, Defines.svc_packetentities); e = 1; ent = GameBase.g_edicts[e]; while (e < GameBase.num_edicts) { // ignore ents without visible models unless they have an effect if (ent.inuse && ent.s.number != 0 && (ent.s.modelindex != 0 || ent.s.effects != 0 || ent.s.sound != 0 || ent.s.event != 0) && 0 == (ent.svflags & Defines.SVF_NOCLIENT)) MSG.WriteDeltaEntity(nostate, ent.s, buf, false, true); e++; ent = GameBase.g_edicts[e]; } MSG.WriteShort(buf, 0); // end of packetentities // now add the accumulated multicast information SZ.Write(buf, SV_INIT.svs.demo_multicast.data, SV_INIT.svs.demo_multicast.cursize); SZ.Clear(SV_INIT.svs.demo_multicast); // now write the entire message to the file, prefixed by the length len = EndianHandler.swapInt(buf.cursize); try { //fwrite (len, 4, 1, svs.demofile); SV_INIT.svs.demofile.writeInt(len); //fwrite (buf.data, buf.cursize, 1, svs.demofile); SV_INIT.svs.demofile.write(buf.data, 0, buf.cursize); } catch (IOException e1) { Com.Printf("Error writing demo file:" + e); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -