public void Init() { snap = new ClientSnapshot(); // mouseDx = new int[3]; // mouseDy = new int[3]; entityBaselines = new EntityState[CConstVar.MAX_SNAPSHOT_ENTITIES * CConstVar.PACKET_BACKUP]; // outPackets = new OutPacket[CConstVar.PACKET_BACKUP]; }
public override void Update(GameTime gameTime) { if (!world.Player.IsDead) { ClientSnapshot snapshot = ClientSnapshot.SnapShot(world); if (previousSnapshot.playerData != snapshot.playerData) { SendMessage(MessageContentType.PlayerUpdate, snapshot.playerData.ID, snapshot.playerData); } } // read new data from server server.Update(); }
private void DeltaEntity(MsgPacket msg, ClientSnapshot frame, int newNum, ref EntityState old, bool unchanged) { EntityState state = clientActive.parseEntities[clientActive.parseEntitiesIndex & (CConstVar.MAX_PARSE_ENTITIES - 1)]; if (unchanged) { old.CopyTo(state); } else { msg.ReadDeltaEntity(ref old, ref state, newNum); } if (state.entityIndex == (CConstVar.MAX_GENTITIES - 1)) { return; } clientActive.parseEntitiesIndex++; frame.numEntities++; }
//TODO:这里有问题,这个函数做了一个假设,可以新增entity,但是不能删除entity,因为删除了,index就会出现错乱 //不过其实问题不大,因为是用的index,所以entity变换成为另外一个entity也不是问题(删除的话先不管,如果新增,就补位到那个entity的位置)。 private void ParseEntities(MsgPacket packet, ClientSnapshot oldframe, ClientSnapshot newframe) { int newIndex; EntityState oldState = new EntityState(); int oldParseIndex, oldEntIndex; newframe.parseEntitiesIndex = clientActive.parseEntitiesIndex; newframe.numEntities = 0; // oldParseIndex = 0; // oldState = if (oldframe == null) { oldEntIndex = 99999; } else { if (oldParseIndex >= oldframe.numEntities) { oldEntIndex = 99999; } else { oldState = clientActive.parseEntities[(oldframe.parseEntitiesIndex + oldParseIndex) & (CConstVar.MAX_PARSE_ENTITIES - 1)]; oldEntIndex = oldState.entityIndex; } } while (true) { //读取entity的索引值 //服务器会根据number从小到大排序,保证小的总在前面 newIndex = packet.ReadBits(CConstVar.GENTITYNUM_BITS); if (newIndex == (CConstVar.MAX_GENTITIES - 1)) { break; } if (packet.CurPos > packet.CurSize) { CLog.Error("ParseEntities: end of message"); break; } while (oldEntIndex < newIndex) { //来自旧数据包中的一个或者多个entity没有发生变化 if (CConstVar.ShowNet == 3) { CLog.Info("entity unchanged: %d", oldEntIndex); } DeltaEntity(packet, newframe, oldEntIndex, ref oldState, true); oldParseIndex++; if (oldParseIndex >= oldframe.numEntities) { oldEntIndex = 99999; } else { oldState = clientActive.parseEntities[(oldframe.parseEntitiesIndex + oldParseIndex) & (CConstVar.MAX_PARSE_ENTITIES - 1)]; oldEntIndex = oldState.entityIndex; } } if (oldEntIndex == newIndex) { //增量来自于前一帧 if (CConstVar.ShowNet == 3) { CLog.Info("delta entity: %d", newIndex); } DeltaEntity(packet, newframe, newIndex, ref oldState, false); oldParseIndex++; if (oldParseIndex >= oldframe.numEntities) { oldEntIndex = 99999; } else { oldState = clientActive.parseEntities[(oldframe.parseEntitiesIndex + oldParseIndex) & (CConstVar.MAX_PARSE_ENTITIES - 1)]; oldEntIndex = oldState.entityIndex; } continue; } //上一帧中没有对应的数据 if (oldEntIndex > newIndex) { if (CConstVar.ShowNet == 3) { CLog.Info("base line entity: %d", newIndex); } DeltaEntity(packet, newframe, newIndex, ref clientActive.entityBaselines[newIndex], false); continue; } } //oldframe内剩下的entities都直接复制过去 //被标记为删除的entity,parseEntitiesIndex不会增加,然后被后续的entity覆盖 while (oldEntIndex != 99999) { if (CConstVar.ShowNet == 3) { CLog.Info("unchanged entity: %d", oldEntIndex); } DeltaEntity(packet, newframe, oldEntIndex, ref oldState, true); oldParseIndex++; if (oldParseIndex >= oldframe.numEntities) { oldEntIndex = 99999; } else { oldState = clientActive.parseEntities[(oldframe.parseEntitiesIndex + oldParseIndex) & (CConstVar.MAX_PARSE_ENTITIES - 1)]; oldEntIndex = oldState.entityIndex; } } }
//如果snapshot解析正确,它会被复制到snap中,并被存储在snapshots[] //如果snapshot因为任何原因不合适,不会任何改变任何state public void ParseSnapshot(MsgPacket packet) { int len; ClientSnapshot old = new ClientSnapshot(); ClientSnapshot newSnap = new ClientSnapshot(); int deltaNum; int oldMessageNum; int i, packetNum; var connection = CDataModel.Connection; //获取可靠的acknowledge number //所有从服务器发送到客户端的消息reliableAcknowledge = ReadLong(); //将新的snapshot读取到临时缓冲中 //如果合适就复制到snap中 newSnap.serverCommandNum = connection.serverCommandSequence; newSnap.serverTime = packet.ReadInt(); this.paused = 0; newSnap.messageNum = connection.serverMessageSequence; deltaNum = packet.ReadByte(); if (deltaNum == 0) { newSnap.deltaNum = -1; } else { newSnap.deltaNum = newSnap.messageNum - deltaNum; } newSnap.snapFlags = (SnapFlags)packet.ReadByte(); // var clientActive = CDataModel.GameState.ClientActive; if (newSnap.deltaNum <= 0) { newSnap.valid = true; old = null; connection.demoWaiting = false; } else { old = clientActive.snapshots[newSnap.deltaNum & CConstVar.PACKET_MASK]; if (!old.valid) { CLog.Error("old snapshot is invalid"); } else if (old.messageNum != newSnap.deltaNum) { CLog.Info("Delta frame too old"); } else if (clientActive.parseEntitiesIndex - old.parseEntitiesIndex > CConstVar.MAX_PARSE_ENTITIES - CConstVar.MAX_SNAPSHOT_ENTITIES) { CLog.Info("Delta parseEntitiesNum too old"); } else { newSnap.valid = true; } } // CLog.Info("begin playerstate at pos:{0}", packet.CurPos); if (old != null) { packet.ReadDeltaPlayerstate(old.playerState, newSnap.playerState); } else { // PlayerState tmpP = default(PlayerState); packet.ReadDeltaPlayerstate(null, newSnap.playerState); } // CLog.Info("begin packet entities at pos:{0}", packet.CurPos); ParseEntities(packet, old, newSnap); //如果不合适,就弹出所有的内容,因为它已经被读出。 if (!newSnap.valid) { return; } //清除最后接收到的帧和当前帧之间的所有帧的valid标记,所以如果有丢掉的消息 //它看起来就不会像是从buffer中增量更新而得到的合适的帧。 oldMessageNum = clientActive.snap.messageNum + 1; if (newSnap.messageNum - oldMessageNum >= CConstVar.PACKET_BACKUP) { oldMessageNum = newSnap.messageNum - (CConstVar.PACKET_BACKUP - 1); } for (; oldMessageNum < newSnap.messageNum; oldMessageNum++) { clientActive.snapshots[oldMessageNum & CConstVar.PACKET_MASK].valid = false; } clientActive.snap = newSnap; clientActive.snap.ping = 999; for (i = 0; i < CConstVar.PACKET_BACKUP; i++) { packetNum = (connection.NetChan.outgoingSequence - 1 - i) & CConstVar.PACKET_MASK; if (clientActive.snap.playerState.commandTime >= clientActive.outPackets[packetNum].serverTime) { clientActive.snap.ping = this.realTime - clientActive.outPackets[packetNum].realTime; break; } } //保存当前帧在缓冲中,用来后来做增量比较 clientActive.snapshots[clientActive.snap.messageNum & CConstVar.PACKET_MASK] = clientActive.snap; if (CConstVar.ShowNet == 3) { CLog.Info("snapshot: {0} delta: {1} ping:{2}", clientActive.snap.messageNum, clientActive.snap.deltaNum, clientActive.snap.ping); } clientActive.newSnapshots = true; }
public override void SnapShot() { previousSnapshot = ClientSnapshot.SnapShot(world); }