public override void Update() { if (this.Active) { this.Position += Velocity; m_LifeTick += TICK; if (m_LifeTick > 2.0f) { m_LifeTick = 0.0f; this.Active = false; this.Velocity = Vector2.Zero; } // Check Collisions foreach (GameObject go in m_CollisionObjects) { if (go.Active) { if (this.Bounds().Intersects(go.Bounds())) { go.Active = false; // If this object is not set to update and send out packets every frame then can force it here as they need to know its not active if (!go.IsUpdatable()) { PacketDefs.PlayerInputUpdatePacket updatePacket = new PacketDefs.PlayerInputUpdatePacket( go.UnqId(), go.Position.X, go.Position.Y, go.FrameX(), go.FrameY(), go.Active); ServerManager.instance.SendAllUdp(fastJSON.JSON.ToJSON( updatePacket, PacketDefs.JsonParams())); } this.Active = false; // Add exp for killimg enemy GameClient client = ServerManager.instance.GetClient(InvokedBy); if (client != null) { client.localExpCache += 2; // Send TCP pack with new exp update, note* only hit the database to increment exp when the level is finished PacketDefs.UpdateExpPacket flp = new PacketDefs.UpdateExpPacket(client.localExpCache, PacketDefs.ID.OUT_TCP_ExpQueery); ServerManager.instance.SendTcp(client.tcpSocket, fastJSON.JSON.ToJSON(flp, PacketDefs.JsonParams())); } } } } } }
private void Dead() { m_MillisPerFrame = 0.07f; frameX = 0;// 7; Position = Player.SpawnPosition(); Velocity = Vector2.Zero; m_Health = MAX_HEALTH; m_Hurt = false; m_Dying = false; m_HurtCounter = 0.0f; // Send UDP pack with new health PacketDefs.PlayerHealthPacket hp = new PacketDefs.PlayerHealthPacket(m_Health); ServerManager.instance.SendUdp(m_ClientId, fastJSON.JSON.ToJSON(hp, PacketDefs.JsonParams())); }
static void Main(string[] args) { PacketDefs.Start(); // Start broadcasting thread Thread bcastThread = new Thread(new ThreadStart(broadCast_t)); bcastThread.Name = "BroadcastThread"; bcastThread.Start(); // Run the game sim loop on another thread Thread gameLoopThread = new Thread(new ThreadStart(GameSimulation.instance.Run)); gameLoopThread.Name = "GameLoopThread"; gameLoopThread.Start(); // Listen for new clients and handle incoming packets AsynchSocketListener server = new AsynchSocketListener(); server.StartListeningForNewClients(); GameSimulation.instance.Shutdown(); Console.ReadLine(); }
private void AcceptCallback(IAsyncResult ar) { allDone.Set(); // ---- Set up tcp socket ---- Socket listener = (Socket)ar.AsyncState; Socket localTcp = listener.EndAccept(ar); // ---- Generate a state object to pass around Async calls ---- TcpStateObject tcpStateObj = new TcpStateObject(); tcpStateObj.tcpSocket = localTcp; // ---- Add a new client with this Tcp socket and get the hash ---- int hash = m_ServerManager.AddNewClient(tcpStateObj.tcpSocket); // ---- Gen a Udp state object on free system port---- IPEndPoint localUpdEndPt = new IPEndPoint(IPAddress.Parse(ServerDefs.GetLocalIPAddress()), 0); UdpClient localUdp = new UdpClient(localUpdEndPt); UdpStateObject udpStateObj = new UdpStateObject(); udpStateObj.endPoint = localUpdEndPt; udpStateObj.udpSocket = localUdp; // Resolve system generated port of local udp socket int port = ((IPEndPoint)localUdp.Client.LocalEndPoint).Port; Logger.Log(string.Format("Listening for UDP connection on port {0}", port)); // Store this in client data m_ServerManager.SetLocalUdpPort(hash, port); // **Important -- SEND Register Function and give them their id which they must store, and use in all packets so we know who they are, also send them local udp port that we are listening for them on. m_ServerManager.SendTcp(tcpStateObj.tcpSocket, fastJSON.JSON.ToJSON(new PacketDefs.connectPacket(hash, port), PacketDefs.JsonParams())); // ---- Begin Async Tcp receive for this client tcpStateObj.tcpSocket.BeginReceive(tcpStateObj.buffer, 0, ServerDefs.BUFF_SIZE, 0, new AsyncCallback(TcpReadCallback), tcpStateObj ); // ---- The client knows this local udp port, so if/when we get a message from them on this, we can add their end // point to the client hash table and connect a local udp Socket to that end point which is also stored and // completes the data structure for this client localUdp.BeginReceive(new AsyncCallback(UdpInitialReadCallback), udpStateObj); Logger.Log("New client connected to server"); Logger.Log(string.Format("Number of clients connected {0}.\nNew client TCP Endpoint {1}.\nWaiting for udp connection on port {2}", m_ServerManager.NumClients(), localTcp.RemoteEndPoint, port)); }
private void CheckCollisions() { // ---- Resolve collision ---- bool contactLeft = false, contactRight = false, contactYbottom = false, contactYtop = false; Vector2 predicted_speed = this.Velocity;; float projectedMoveX, projectedMoveY, originalMoveX, originalMoveY; originalMoveX = predicted_speed.X; originalMoveY = predicted_speed.Y; // This needs to be from the qyadtree foreach (GameObject colTest in GameSimulation.instance.GetObjects()) { if ((colTest.TypeId() == GameObjectType.Wall || colTest.TypeId() == GameObjectType.DestructablePlatform) && colTest.Active) { for (int dir = 0; dir < 4; dir++) { if (dir == UP && predicted_speed.Y > 0) { continue; } if (dir == DOWN && predicted_speed.Y < 0) { continue; } if (dir == LEFT && predicted_speed.X > 0) { continue; } if (dir == RIGHT && predicted_speed.X < 0) { continue; } projectedMoveX = (dir >= LEFT ? predicted_speed.X : 0); projectedMoveY = (dir < LEFT ? predicted_speed.Y : 0); while ((colTest.Bounds().Contains(this.points[dir * 2].X + (int)this.Position.X + (int)projectedMoveX, this.points[dir * 2].Y + (int)this.Position.Y + (int)projectedMoveY) || colTest.Bounds().Contains(this.points[dir * 2 + 1].X + (int)this.Position.X + (int)projectedMoveX, this.points[dir * 2 + 1].Y + (int)this.Position.Y + (int)projectedMoveY))) { if (dir == UP) { projectedMoveY++; } if (dir == DOWN) { projectedMoveY--; } if (dir == LEFT) { projectedMoveX++; } if (dir == RIGHT) { projectedMoveX--; } } if (dir >= LEFT && dir <= RIGHT) { predicted_speed.X = projectedMoveX; } if (dir >= UP && dir <= DOWN) { predicted_speed.Y = projectedMoveY; } } // Resolve contact if (predicted_speed.Y > originalMoveY && originalMoveY < 0) { contactYtop = true; } if (predicted_speed.Y < originalMoveY && originalMoveY > 0) { contactYbottom = true; } if (predicted_speed.X - originalMoveX < -0.01f) { contactRight = true; } if (predicted_speed.X - originalMoveX > 0.01f) { contactLeft = true; } // Resolve collision from contact if (contactYbottom) { this.Velocity.Y = 0; this.Grounded = true; } else if (contactYtop) { this.Velocity.Y = 0; } if (contactLeft || contactRight) { this.Velocity.X = 0; } } else if (colTest.TypeId() == GameObjectType.Exit) { if (this.Bounds().Intersects(colTest.Bounds())) { // Stop updating this object Active = false; // Send Back to previous position this.Position = Player.SpawnPosition(); this.Velocity = Vector2.Zero; GameClient client = ServerManager.instance.GetClient(m_ClientId); if (client != null) { client.inGame = false; // NOTE** This is the only time we want to update the database (when they finish the level) client.localExpCache += 30; // Give this client some experience on database ServerManager.instance.UpdateClientExpDB(client.userName, client.localExpCache); // Send him back to the lobby : TODO Get EXP from DB PacketDefs.UpdateExpPacket flp = new PacketDefs.UpdateExpPacket(client.localExpCache, PacketDefs.ID.OUT_TCP_FinishLevel); ServerManager.instance.SendTcp(client.tcpSocket, fastJSON.JSON.ToJSON(flp, PacketDefs.JsonParams())); if (!GameSimulation.instance.ArePeopleInGame()) { // No one is in-game so clear data GameSimulation.instance.ScheduleClearGameData(); return; } } } } else if (colTest.TypeId() == GameObjectType.GoldSkull) { if (this.Bounds().Intersects(colTest.Bounds()) && colTest.Active) { colTest.Active = false; // Send out a packet here informing them it's deactivated (rather than using standward way and doing it every frame) PacketDefs.PlayerInputUpdatePacket updatePacket = new PacketDefs.PlayerInputUpdatePacket( colTest.UnqId(), colTest.Position.X, colTest.Position.Y, colTest.FrameX(), colTest.FrameY(), colTest.Active); ServerManager.instance.SendAllUdp(fastJSON.JSON.ToJSON( updatePacket, PacketDefs.JsonParams())); // Add exp for collecting skull GameClient client = ServerManager.instance.GetClient(m_ClientId); if (client != null) { client.localExpCache += 10; // Send TCP pack with new exp update, note* only hit the database to increment exp when the level is finished PacketDefs.UpdateExpPacket flp = new PacketDefs.UpdateExpPacket(client.localExpCache, PacketDefs.ID.OUT_TCP_ExpQueery); ServerManager.instance.SendTcp(client.tcpSocket, fastJSON.JSON.ToJSON(flp, PacketDefs.JsonParams())); } } } else if (IsHazard(colTest.TypeId())) { if (!m_Hurt) { if (this.Bounds().Intersects(colTest.Bounds()) && colTest.Active) { //if (Math.Abs(Velocity.X) >= 1.0f) //{ Velocity = new Vector2(-(float)m_Facing * 10, -20); //} //else //{ // Velocity.Y = -30.0f; //} m_Hurt = true; Grounded = true; m_Health -= 1; // Send UDP pack with new health PacketDefs.PlayerHealthPacket hp = new PacketDefs.PlayerHealthPacket(m_Health); ServerManager.instance.SendUdp(m_ClientId, fastJSON.JSON.ToJSON(hp, PacketDefs.JsonParams())); } } } } }
// ---- Function Pointers ---- private bool CreateAccountMsg(Dictionary <string, object> json) { Logger.Log("Got Create account message"); // Data to extract form this packet string name = ""; string password = ""; int clientId = -1; // Extract the id of the sender if (json.ContainsKey("id")) { clientId = (int)((long)json["id"]); } else { Logger.Log("Error Parsing client id in start game packet", Logger.LogPrio.Error); return(false); } if (json.ContainsKey("userName")) { name = (string)json["userName"]; } if (json.ContainsKey("password")) { password = (string)json["password"]; } // Send Packet with the return value of AddnewUserToDatabase as the argument for success PacketDefs.msgPacket returnPack = new PacketDefs.msgPacket(); if (string.IsNullOrEmpty(name)) { returnPack.msg = "Error: Name is null or empty"; } else if (string.IsNullOrEmpty(password)) { returnPack.msg = "Error: Password is null or empty"; } else { returnPack.msg = ServerManager.instance.AddNewClientToDatabase(clientId, name, password); } ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(returnPack, PacketDefs.JsonParams())); return(true); }
private bool LeaderboardRequestMsg(Dictionary <string, object> json) { // Just send them back the request int clientId = -1; if (json.ContainsKey("id")) { clientId = (int)((long)json["id"]); } GameClient client = ServerManager.instance.GetClient(clientId); if (client != null) { PacketDefs.LeaderboardPacket lbp = new PacketDefs.LeaderboardPacket(ServerManager.instance.GetLeaderBoard()); ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(lbp, PacketDefs.JsonParams())); return(true); } return(false); }
private bool ExpQueeryMsg(Dictionary <string, object> json) { // Just send them back the request int clientId = -1; if (json.ContainsKey("id")) { clientId = (int)((long)json["id"]); } GameClient client = ServerManager.instance.GetClient(clientId); if (client != null) { PacketDefs.UpdateExpPacket flp = new PacketDefs.UpdateExpPacket(ServerManager.instance.GetClientExp(client.userName), PacketDefs.ID.OUT_TCP_ExpQueery); ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(flp, PacketDefs.JsonParams())); return(true); } return(false); }
private bool StartGameMsg(Dictionary <string, object> json) { // This is complicated so will do my best to comment, even for myself in the future // There are 4 players allowed to drop in/out per game, this tries to cover all possible scenarios that I could think of /* * There are a number of different conditionns that need to be considered * - The player needs to have an account and be logged in to start a game * - If the above conditions are not met, he will simply get an error message explainig why * - This may be the first play that starts the game, if so the level will be constructed, he will be sent a packet for info on his playe * - If there are already clients online, then they need to know about this new player who has joined, and he needs to know about himself and them * - Next... need to consider the fact that the other clients on the server are in game or not, if they are not in a game, and in the lobby then they * do NOT need to know about this new player until they have started their own game * - If all players reach the exit, then the game simulation is cleared from memory * - Up to 4 players can join the same game at any time, and the game session is considered over when all players have either reached the goal or quit out * - In an edge case situation.... two players start a game >> player 1 finished level and goes back to lobby >> player 2 is still playing >> player 1 can re-enter * using the same internal game object, the player count will still be incremented as this could go on forever otherwise */ int clientId = -1; // Extract the id of the sender if (json.ContainsKey("id")) { clientId = (int)((long)json["id"]); } else { Logger.Log("Error Parsing client id in start game packet", Logger.LogPrio.Error); } // Check that this id is in our client hash table if (!m_ServerManager.ClientExists(clientId)) { Logger.Log(string.Format("Error client id {0} does not exist", clientId), Logger.LogPrio.Error); return(false); } // Client must be logged in!! if (Server.ServerManager.instance.GetClient(clientId).loggedIn == false) { PacketDefs.msgPacket returnPack = new PacketDefs.msgPacket(); returnPack.msg = "Error: not logged in"; returnPack.success = false; ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(returnPack, PacketDefs.JsonParams())); return(false); } // Game must not be full !! else if (m_GameSimulation.GetPlayersInGame() >= 4) { PacketDefs.msgPacket returnPack = new PacketDefs.msgPacket(); returnPack.msg = "Game is full please wait"; returnPack.success = false; ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(returnPack, PacketDefs.JsonParams())); return(false); } else { // This is first client so load level data if (!m_GameSimulation.IsGameDataLoaded()) { m_GameSimulation.LoadLevel(0); } GameClient thisClient = ServerManager.instance.GetClient(clientId); // Check if he is re-entering the same game if (thisClient.playerObjectHandle > -1) { // Do we have a match foreach (GameObject go in GameSimulation.instance.GetPlayers()) { if (go.UnqId() == thisClient.playerObjectHandle && go.Active == false) { // The players already on will get an update to activate this in next tick go.Active = true; // Increment counter GameSimulation.instance.AddNewPlayerToSession(); } } } // Weird edge case: Previous client quit, but we still have a re-useable game object in memory so give him that else if (GameSimulation.instance.GetPlayers().Count == ServerManager.instance.NumClients()) { foreach (GameObject go in GameSimulation.instance.GetPlayers()) { if (go.Active == false) { // The players already on will get an update to activate this in next tick go.Active = true; // Increment counter GameSimulation.instance.AddNewPlayerToSession(); // Set the internal memoory handle store in client data m_ServerManager.SetPlayerHandle(clientId, go.UnqId()); go.IsClient = 1; } } } else { // This client is new to this game // Set the internal memoory handle store in client data m_ServerManager.SetPlayerHandle(clientId, m_GameSimulation.NumObjects()); // Add new client to game sim GameObject newPlayer = new Player(Player.SpawnPosition(), GameObjectType.Player, m_GameSimulation.NumObjects(), 1, true, clientId, new Vector2(96, 96), new ColliderOffset(26, 26, 30, 0)); //new Vector2(128, 128), new ColliderOffset(46,46,50,0)); m_GameSimulation.AddGameObject(newPlayer); // Create Packet of one game object (this player) to send to other clients already on server with just this player. *note* last param (isClient) is set to 0 intentionally PacketDefs.MultiGameObjectPacket thisClientPacket = new PacketDefs.MultiGameObjectPacket(1); thisClientPacket.objects[0] = new PacketDefs.GameObjectPacket( (int)newPlayer.TypeId(), newPlayer.UnqId(), newPlayer.Position.X, newPlayer.Position.Y, 0); // This flag signifies if we actually need to load the level,m because the other client is either in game or lobby then we don't want this thisClientPacket.loadLevel = false; // 1 - Send any clients on the server the new one that has been added string data = fastJSON.JSON.ToJSON(thisClientPacket, PacketDefs.JsonParams()); foreach (KeyValuePair <int, GameClient> kvp in ServerManager.instance.GetClients()) { // - Make sure it is not this client: He is included in the all clients packet and doesnt need to know // - Make sure they are logged : Because they need to be // - Make sure they are in game: Because they will get duplicates when they call this function otherwise // This basically allows controls over the different stages, handles whether we are logged in or not and allows // to drop in the game at any time if (kvp.Key != clientId && kvp.Value.loggedIn && kvp.Value.inGame) { ServerManager.instance.SendTcp(kvp.Value.tcpSocket, data); } } } // Create Packet for list of all clients now to send to new player including himself PacketDefs.MultiGameObjectPacket allClientsPacket = new PacketDefs.MultiGameObjectPacket(m_ServerManager.NumClients()); allClientsPacket.loadLevel = true; // Fill it with data int i = 0; foreach (GameObject p in m_GameSimulation.GetObjects()) { if (p.TypeId() == GameObjectType.Player) { allClientsPacket.objects[i] = new PacketDefs.GameObjectPacket( (int)p.TypeId(), p.UnqId(), p.Position.X, p.Position.Y, p.IsClient ); ++i; } } // Prevents duplicates thisClient.inGame = true; // 2 - Send the new client his own player details and the other players in the game m_ServerManager.SendTcp(thisClient.tcpSocket, fastJSON.JSON.ToJSON(allClientsPacket, PacketDefs.JsonParams())); // Set all players 'isClient' flag to null now that packets are sent foreach (GameObject player in GameSimulation.instance.GetPlayers()) { player.IsClient = 0; } return(true); } }
private bool UserLoginMsg(Dictionary <string, object> json) { Logger.Log("Got Login message"); // Data to extract form this packet string name = ""; string password = ""; int clientId = -1; // Extract the id of the sender if (json.ContainsKey("id")) { clientId = (int)((long)json["id"]); } else { Logger.Log("Error Parsing client id in start game packet", Logger.LogPrio.Error); return(false); } if (json.ContainsKey("userName")) { name = (string)json["userName"]; } if (json.ContainsKey("password")) { password = (string)json["password"]; } // Send Packet with the return value of AddnewUserToDatabase as the argument for success PacketDefs.msgPacket returnPack = new PacketDefs.msgPacket(); // Check this first as it's quicker than hitting database if (!ServerManager.instance.ClientExists(clientId)) { string err = string.Format("Tried to create account with unknown client id: {0}", clientId); Logger.Log(err, Logger.LogPrio.Error); returnPack.success = false; returnPack.msg = err; } else if (ServerManager.instance.GetClient(clientId).loggedIn) { returnPack.success = false; returnPack.msg = "You are already logged in"; } else { returnPack.msg = ServerManager.instance.Login(name, password, clientId, out returnPack.success); } // Send the info as udp ServerManager.instance.SendUdp(clientId, fastJSON.JSON.ToJSON(returnPack, PacketDefs.JsonParams())); // Send them an exp update GameClient thisClient = ServerManager.instance.GetClient(clientId); if (thisClient != null) { int expFromDB = ServerManager.instance.GetClientExp(name); thisClient.localExpCache = expFromDB; PacketDefs.UpdateExpPacket flp = new PacketDefs.UpdateExpPacket(expFromDB, PacketDefs.ID.OUT_TCP_ExpQueery); ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(flp, PacketDefs.JsonParams())); return(true); } else { return(false); } }