Example #1
0
	private void AddEntToSnapshot(SvEntityState svEntity, SharedEntity gEnt, List<int> entitiesIndex){
		//如果已经添加了,就不再次添加
		if(svEntity.snapshotCounter == snapshotCounter){
			return;
		}
		svEntity.snapshotCounter = snapshotCounter;
		if(entitiesIndex.Count >= CConstVar.MAX_SNAPSHOT_ENTITIES){
			return;
		}
		entitiesIndex.Add(gEnt.s.entityIndex);
	}
        // Adds a shared entity such as a negative keyword list to the account's library.
        // Lists in the account's library can be associated with any campaign within the account.

        private async Task <AddSharedEntityResponse> AddSharedEntityAsync(
            SharedEntity sharedEntity,
            IList <SharedListItem> listItems)
        {
            var request = new AddSharedEntityRequest
            {
                ListItems    = listItems,
                SharedEntity = sharedEntity
            };

            return(await Service.CallAsync((s, r) => s.AddSharedEntityAsync(r), request));
        }
Example #3
0
    public void StoreHistory(SharedEntity sEnt, int time)
    {
        historyHead++;
        if (historyHead >= CConstVar.NUM_CLIENT_HISTORY)
        {
            historyHead = 0;
        }

        int head = historyHead;

        history[head].mins          = sEnt.r.mins;
        history[head].maxs          = sEnt.r.maxs;
        history[head].currentOrigin = sEnt.r.currentOrigin;
        history[head].time          = time;
    }
Example #4
0
	private void ClientEnterWorld(ClientNode cl, UserCmd cmd){
		cl.state = ClientState.ACTIVE;
		int clNum = Array.IndexOf(clients, cl);
		SharedEntity ent = gEntities[clNum];
		ent.s.entityIndex = clNum;
		cl.gEntity = ent;

		cl.deltaMessage = -1;
		cl.lastSnapshotTime = 0; //立即产生一个snapshot

		if(cmd != null){
			cmd.CopyTo(cl.lastUserCmd);
		}else{
			cl.lastUserCmd.Reset();
		}

		CDataModel.GameSimulate.ClientBegin(clNum);
	}
Example #5
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++;
		}
	}
        // Adds a shared entity such as a negative keyword list to the account's library. 
        // Lists in the account's library can be associated with any campaign within the account. 

        private async Task<AddSharedEntityResponse> AddSharedEntityAsync(
            SharedEntity sharedEntity,
            IList<SharedListItem> listItems)
        {
            var request = new AddSharedEntityRequest
            {
                ListItems = listItems,
                SharedEntity = sharedEntity
            };

            return (await Service.CallAsync((s, r) => s.AddSharedEntityAsync(r), request));
        }
 public void Init()
 {
     instance = new SharedEntity();
 }
Example #8
0
	private void DirectConnect(IPEndPoint from)
	{
		ClientNode cl = null;
		int newClIdx = 0;
		ClientNode newcl = null;
		// ClientNode temp = new ClientNode();

		string ip;
		var userinfo = CDataModel.CmdBuffer.Argv(1);
		int version = System.Convert.ToInt32(CUtils.GetValueForKey(userinfo, "protocol"));

		if(version != CConstVar.Protocol){
			CNetwork_Server.Instance.OutOfBandSend(NetSrc.SERVER, from, string.Format("server protocol mismatches with client. server:%d, client:%d", CConstVar.Protocol, version));
			return;
		}

		int chNum = System.Convert.ToInt32(CUtils.GetValueForKey(userinfo, "challenge"));
		// int qport = System.Convert.ToInt32(CUtils.GetValueForKey(userinfo, "qport"));
		int qport = from.Port;

		int port = System.Convert.ToInt32(CUtils.GetValueForKey(userinfo, "port"));
		from.Port = port;

		for(int i = 0; i < CConstVar.MAX_CLIENTS; i++){
			cl = clients[i];
			if(cl.state == ClientState.FREE){
				continue;
			}

			if(from.Address.Equals(cl.netChan.remoteAddress.Address) && (cl.netChan.qport == qport || from.Port == cl.netChan.remoteAddress.Port)){
				if(time - cl.lastConnectTime < CConstVar.reconnectLimit * 1000){
					CLog.Info("{0}: reconnect rejected : too soon", from);
					return;
				}
				break;
			}
		}

		if(IPAddress.IsLoopback(from.Address)){
			ip = "localhost";
		}else{
			ip = from.Address.ToString();
		}

		CUtils.SetValueForKey(ref userinfo, "ip", ip);
		if(IPAddress.IsLoopback(from.Address)){
			int ping;
			SvChallenge ch;
			int i;
			for(i = 0; i < CConstVar.MAX_CHALLENGES; i++){
				if(from.Address.Equals(challenges[i].adr.Address)){
					if(chNum == challenges[i].challenge){
						break;
					}
				}
			}

			if(i == CConstVar.MAX_CHALLENGES){
				CNetwork_Server.Instance.OutOfBandSend(NetSrc.SERVER, from, string.Format("no or bad challenge for your address %s", from));
				return;
			}

			ch = challenges[i];
			if(ch.wasrefused){
				return;
			}
			ping = time - ch.pingTime;

			//局域网不判断ping
			if(!CNetwork.IsLANAddress(from.Address)){
				if(CConstVar.minPing > 0 && ping < CConstVar.minPing){
					CNetwork_Server.Instance.OutOfBandSend(NetSrc.SERVER, from, "server is for high pings only");
					ch.wasrefused = true;
					return;
				}

				if(CConstVar.maxPing > 0 && ping < CConstVar.maxPing){
					CNetwork_Server.Instance.OutOfBandSend(NetSrc.SERVER, from, "server is for high pings only");
					ch.wasrefused = true;
					return;
				}
			}

			ch.connected = true;
		}

		//  = temp;

		Action newClient = ()=>{
			// newcl = temp;
			if(newcl == null) newcl = new ClientNode();
			SharedEntity ent = gEntities[newClIdx];
			newcl.gEntity = ent;
			newcl.challenge = chNum;
		
			newcl.netChan.SetUp(NetSrc.SERVER, from, chNum, qport);
			newcl.netChanQueue.Reset();
			newcl.userInfo = userinfo;

			//发送连接消息给客户端
			CNetwork_Server.Instance.OutOfBandSend(NetSrc.SERVER, from, string.Format("connectResponse {0} {1} {2}", chNum, CConstVar.ServerPort, CConstVar.serverID));

			newcl.state = ClientState.CONNECTED;
			newcl.lastSnapshotTime = 0;
			newcl.lastPacketTime = time;
			newcl.lastConnectTime = time;

			//当收到来自客户端的第一条消息,就会发现这是来自不同的serverid,而gamestate消息没有发送,强制传输
			newcl.gamestateMessageNum = -1;

			int count = 0;
			for(int i = 0; i < CConstVar.MAX_CLIENTS; i++){
				if(clients[i].state >= ClientState.CONNECTED){
					count++;
				}
			}
			if(count == 1 || count == CConstVar.MAX_CLIENTS){
				nextHeartbeatTime = -999999;
			}

			// ClientEnterWorld(newcl, null);
		};
		
		//如果有一个这个ip的连接,重用它
		for(int i = 0; i < CConstVar.MAX_CLIENTS; i++){
			cl = clients[i];
			if(cl.state == ClientState.FREE){
				continue;
			}

			if(from.Address.Equals(cl.netChan.remoteAddress.Address) && (cl.netChan.qport == qport || from.Port == cl.netChan.remoteAddress.Port)){
				CLog.Info("{0}: reconnect rejected : too soon", from);
				newcl = cl;
				newClIdx = i;
				newClient();
				break;
			}
		}

		//找到一个client
		//如果CConstVar.PrivateClients > 0, 那么会为"password"设置为的客户端保留位置
		//
		string pwd = CUtils.GetValueForKey(userinfo, "password");
		int startIdx = 0;
		if(pwd == CConstVar.PrivatePwd){
			//跳过预留的位置
			startIdx = CConstVar.PrivateClients;
		}

		newcl = null;
		for(int i = startIdx; i < CConstVar.MAX_CLIENTS; i++){
			cl = clients[i];
			if(cl.state == ClientState.FREE){
				newcl = cl;
				newClIdx = i;
				break;
			}
		}

		if(newcl == null){
			if(IPAddress.IsLoopback(from.Address)){
				int count = 0;
				for(int i = startIdx; i < CConstVar.MAX_CLIENTS; i++){
					cl = clients[i];
					if(cl.netChan.isBot){
						count++;
					}
				}

				//如果都是机器人
				if(count >= CConstVar.MAX_CLIENTS - startIdx){
					DropClient(clients[CConstVar.MAX_CLIENTS - 1],"only bots on server");
					newcl = clients[CConstVar.MAX_CLIENTS -1];
					newClIdx = CConstVar.MAX_CLIENTS -1;
				}else{
					CLog.Error("server is full on local connect");
					return;
				}
			}
			else{
				CNetwork_Server.Instance.OutOfBandSend(NetSrc.SERVER, from, "server is full");
				CLog.Info("Rejected a connection. {0}", from);
				return;
			}
		}

		//有一个新的客户端,所有重置reliableSequence和reliableAcknowledge
		if(cl != null){
			cl.reliableAcknowledge = 0;
			cl.reliableSequence = 0;

		}

		newClient();
	}
Example #9
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);
			}
		}
	}
Example #10
0
    // public bool physicss

    public GameEntity()
    {
        sEnt = new SharedEntity();
    }