private void EmitPacketEntities(SvClientSnapshot from, SvClientSnapshot to, MsgPacket msg){ EntityState? oldEnt = null; EntityState? newEnt = null; int oldIndex = 0, newIndex = 0; int oldNum, newNum; int fromNumEnts; if(from == null){ fromNumEnts = 0; }else{ fromNumEnts = from.numEntities; } while(newIndex < to.numEntities || oldIndex < fromNumEnts){ if(newIndex >= to.numEntities){ newNum = 9999; }else{ newEnt = snapshotEntities[(to.firstEntity + newIndex) % numSnapshotEntities]; newNum = newEnt.Value.entityIndex; } if(oldIndex >= fromNumEnts){ oldNum = 9999; }else{ oldEnt = snapshotEntities[(from.firstEntity + oldIndex) % numSnapshotEntities]; oldNum = oldEnt.Value.entityIndex; } //相等表示是同一个entity if(newNum == oldNum){ msg.WriteDeltaEntity(oldEnt, newEnt, false); oldIndex++; newIndex++; continue; } //新增的entity排在前面, if(newNum < oldNum){ oldEnt = svEntities[newNum].baseline; msg.WriteDeltaEntity(oldEnt, newEnt, true); oldEnt = null; newIndex++; continue; } //旧的entity消失了,写入一个字段表示此entity消失了 if(newNum > oldNum){ msg.WriteDeltaEntity(oldEnt, null, true); oldIndex++; continue; } } msg.WriteBits(CConstVar.MAX_GENTITIES - 1, CConstVar.GENTITYNUM_BITS); //packet entities尾端 }
//决定哪一个entity对客户端是可见的,并复制playerState。 //这个函数处理多个递归的入口,但是渲染器不会。 //对于其他玩家看到的视野,clent可以是client.gentity以外的东西 private void BuildClientSnapshot(ClientNode client){ snapshotCounter++; SvClientSnapshot frame = client.frames[client.netChan.outgoingSequence & CConstVar.PACKET_MASK]; frame.numEntities = 0; SharedEntity clEnt = client.gEntity; if(client == null || client.state == ClientState.ZOMBIE){ return; } PlayerState ps = GetClientPlayer(client);//client.playerState; ps.CopyTo(frame.playerState); int clientNum = frame.playerState.clientIndex; if(clientNum < 0 || clientNum > CConstVar.MAX_GENTITIES){ CLog.Error("SvEntity for gEntity: bad gEnt"); } var svEnt = svEntities[clientNum]; svEnt.snapshotCounter = snapshotCounter; Vector3 org = ps.origin; org[2] += ps.viewHeight; var entitiesIndex = new List<int>(CConstVar.MAX_SNAPSHOT_ENTITIES); AddEntitiesVisibleFromPoint(org, frame, entitiesIndex, false); //entitiesIndex里面的entityIndex不一定是连续的,但是有序的,从小到大 entitiesIndex.Sort(); frame.numEntities = 0; frame.firstEntity = nextSnapshotEntities; for(int i = 0; i < entitiesIndex.Count; i++){ var ent = gEntities[i]; snapshotEntities[nextSnapshotEntities % numSnapshotEntities] = ent.s; nextSnapshotEntities++; if(nextSnapshotEntities >= 0x7FFFFFFE){ CLog.Error("SV: nextSnapshotEntities wraped"); } frame.numEntities++; } }
// public PlayerState playerState; public ClientNode(){ state = ClientState.FREE; netChan = new NetChan(); netChanQueue = new CircularBuffer<NetChanBuffer>(10); frames = new SvClientSnapshot[CConstVar.PACKET_BACKUP]; for(int i = 0; i < CConstVar.PACKET_BACKUP; i++){ frames[i] = new SvClientSnapshot(); } // gEntity = new SharedEntity(); // gEntity.r = new EntityShared(); // gEntity.s = new EntityState(); reliableCommands = new char[CConstVar.MAX_RELIABLE_COMMANDS][]; for(int i = 0; i < CConstVar.MAX_RELIABLE_COMMANDS; i++){ reliableCommands[i] = new char[CConstVar.MAX_STRING_CHARS]; } lastUserCmd = new UserCmd(); messageAcknowledge = -1; gamestateMessageNum = -1; // playerState = new PlayerState(); }
// private void AddEntitiesVisibleFromPoint(Vector3 origin, SvClientSnapshot frame, List<int> entitiesIndex, bool portal){ for(int e = 0; e < numEntities; e++){ SharedEntity ent = gEntities[e]; //没有连入的entity就不发送 if(!ent.r.linked){ continue; } if(ent.s.entityIndex != e){ CLog.Error("SV: entity index mismatch, fixing"); ent.s.entityIndex = e; } //entities能被标记为发送给一个客户端 if((ent.r.svFlags & SVFlags.SINGLE_CLIENT) != SVFlags.NONE){ if(ent.r.singleClinet != frame.playerState.clientIndex){ continue; } } //entities可以标记为发送给每个人但是只有一个客户端 if((ent.r.svFlags & SVFlags.NOTSINGLE_CLIENT) != SVFlags.NONE){ if(ent.r.singleClinet == frame.playerState.clientIndex){ continue; } } //entities可以标记为发送给指定掩码的客户端 if((ent.r.svFlags & SVFlags.CLIENT_MASK) != SVFlags.NONE){ if(frame.playerState.clientIndex > 32){ CLog.Error("SVFlags.CLIENT_MASK: clientNum >= 32"); } if((~ent.r.singleClinet & (1 << frame.playerState.clientIndex)) >0){ continue; } } if(ent == null || ent.s.entityIndex < 0 || ent.s.entityIndex >= CConstVar.MAX_GENTITIES){ CLog.Error("SV: entity index not in range"); } var svEnt = svEntities[ent.s.entityIndex]; //不要添加两次entity if(svEnt.snapshotCounter == snapshotCounter){ continue; } //广播的entities总会发送 if((ent.r.svFlags & SVFlags.BROADCAST) != SVFlags.NONE){ AddEntToSnapshot(svEnt, ent, entitiesIndex); continue; } //这里需要进行判断是否可见等 AddEntToSnapshot(svEnt, ent, entitiesIndex); if((ent.r.svFlags & SVFlags.PORTAL) != SVFlags.NONE){ Vector3 dir = ent.s.origin - origin; if(dir.magnitude > ent.s.generic1){ continue; } AddEntitiesVisibleFromPoint(ent.s.origin2, frame, entitiesIndex, true); } } }