Пример #1
0
	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尾端

	}
Пример #2
0
	//决定哪一个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++;
		}
	}
Пример #3
0
	// 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();
	}
Пример #4
0
	//
	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);
			}
		}
	}