public static void Main() { ClockTimer.RecordRunTime(); Console.WriteLine(" ==================================================== "); Console.WriteLine(" Welcome to the BBLegacy Dedicated Server [prototype] "); Console.WriteLine(); Console.WriteLine(" INIFile Management Code by S.T.A. snc (C)2009-2013 "); Console.WriteLine(" Networking System by FatalSleep from The GMCommunity "); Console.WriteLine(" ==================================================== "); Console.WriteLine(); //Fetch the External IP Address, if they're not using local. string TheIPAddress; if (IsLocal == 1) { TheIPAddress = "127.0.0.1"; } else { Console.Write("Fetching IP Address... "); TheIPAddress = getExternalIp(); Console.WriteLine("done."); } UpdateINI Backupper = new UpdateINI(60000); TcpListenerSocket myTcpSocket = new TcpListenerSocket(TheIPAddress, Port, MaxClients, ReadSize, WriteSize, Alignment, PacketHeader); Console.WriteLine("TCP Connection Listener Established (" + TheIPAddress + " :: " + Port + ")"); Console.WriteLine(" - The connection is set to have a maximum of " + MaxClients + " BBLegacy connections."); UdpServerSocket myUdpSocket = new UdpServerSocket(Port, ReadSize, WriteSize, Alignment, PacketHeader); Console.WriteLine("UDP Connection Listener Established (" + TheIPAddress + " :: " + Port + ")"); string Command = ""; Thread.Sleep(3000); Thread.Sleep(1000); Console.WriteLine("You can now type 'help' for some commands."); Console.WriteLine(); Console.WriteLine(" ==================================================== "); while (myTcpSocket.Status == true || myUdpSocket.Status == true) { Command = Console.ReadLine(); CmdSystem.RunCmd(Command, myTcpSocket, myUdpSocket); } ClockTimer.StopRunTime(); }
/// <summary> /// Read and process packets received from the client. /// </summary> /// <param name="Player">Client socket class that is being handled.</param> /// <param name="myServer">Server's handle(listener) socket class.</param> public static void TcpPacketRead(TcpClientSocket Player, TcpListenerSocket myServer) { byte myCheck = Player.ReadBuffer.StartRead(0); var buff = Player.DataStream; //Not all functions require a writeback, but it helps to have this ready. var Write = Player.WriteBuffer; var Read = Player.ReadBuffer; var File = MainServer.SettingsFile; var PLID = Player.ID.ToString(); // Check for packets by searching for packet headers. while (myCheck == Player.HeaderId) { Write.Clear(); Write.WriteUByte(Player.HeaderId); byte myPacketId = Read.ReadUByte(); switch (myPacketId) { /* To READ from the buffer... * float myFloat = Player.ReadBuffer.Readf32(); * int myInteger = Player.ReadBuffer.Readu32(); * string myString = Player.ReadBuffer.ReadStr(); * * To WRITE to the buffer and send... * Player.WriteBuffer.SetPeek( 0 ); * Player.WriteBuffer.Writeu8( TcpNetwork.TcpPacketHeader ); * Player.WriteBuffer.Writeu8( 254 ); * Player.WriteBuffer.SendTcp( Player.DataStream );*/ //They sent this to see if the connection works. Echo their packet back. case Code.ConnectionBegin: { //Assigns the given PlayerID to this specific client. Also the name should've given their name. Player.ID = Read.ReadDouble(); Player.Name = Read.ReadString(); Player.Icon = Read.ReadUByte(); Player.XP = Read.ReadUInt(); //Tells them that they connected. Write.WriteUByte(Code.ConnectionBegin); Write.WriteString(MainServer.WelcomeMessage); Write.WriteBool(MainServer.CanCreateRooms); CmdSystem.AddLog(Player.Name + " has connected (ID:" + Player.ID.ToString() + ")"); Write.SendTcp(Player.DataStream); //If they're admins... if (AdminList.isAdmin(Player.ID)) { Player.Tag = 2; } //If they're not on the list, put them on the list. //This also means that they're new players, 1st time joiners! var b = false; foreach (PlayerListItem i in MainServer.PlayerList) { if (i.ID == Player.ID) { b = true; Player.Tag = i.Tag; i.Link(Player); } } if (!b) { Player.ListSlot = new PlayerListItem(); } Player.ListSlot.Link(Player); Player.ListSlot.GoOnline(); MainServer.Event.PlayerConnected(Player); break; } case Code.ConnectionEnd: { Player.UserImposedDisconnection = true; Player.Connected = false; CmdSystem.AddLog(Player.Name + " has left"); if (Player.ListSlot != null) { Player.ListSlot.GoOffline(); } MainServer.Event.PlayerDisconnected(Player); break; } // == ADD MENU STATUS == //They want to join this room. Returns ID upon success, or a negative number upon failure. case Code.SessionJoin: { var id = Read.ReadUInt(); uint success = 4000000004; byte pnum = 0; String nm = " "; foreach (Room i in MainServer.RoomList) { if (i.id == id) { success = i.Join(Player); pnum = (byte)i.players.Count; nm = i.name; break; } } Write.Clear(); Write.WriteUByte(Player.HeaderId); Write.WriteUByte(Code.SessionJoin); Write.WriteUInt(success); Write.WriteUByte(pnum); byte plst = 1; if (Player.CurrentRoom != null) { plst = Player.CurrentRoom.playstate; } Write.WriteUByte(plst); Write.WriteString(nm); Write.SendTcp(buff); if (success < 4000000000) { Player.ListSlot.GoPlayingOnline(); } //Now that they know they joined, we can now auto-start the room if needed. foreach (Room i in MainServer.RoomList) { if (i.id == id) { if (i.tag == 0 && i.playstate <= 2) { if (i.players.Count > 1 && i.playstate == 1) { i.EnterVoteRoom(); } i.Teamify(); } } } MainServer.Event.PlayerJoinedRoom(Player, Player.CurrentRoom); break; } case Code.SessionLeave: { byte success = 1; Room rm = Player.CurrentRoom; if (Player.CurrentRoom == null) { success = 0; } else { success = Player.CurrentRoom.Remove(Player); } Write.WriteUByte(Code.SessionLeave); Write.WriteUByte(success); Write.SendTcp(Player.DataStream); if (success > 0) { Player.ListSlot.GoOnline(); MainServer.Event.PlayerLeftRoom(Player, rm); } break; } //Creates a session, returning room ID if the operation was successful. case Code.SessionCreate: { //Host, Name, Mode, Team, Team Number, Minutes, Max Players var rs1 = Read.ReadString(); var ub2 = Read.ReadUByte(); var bo3 = Read.ReadBool(); var ub4 = Read.ReadUByte(); var ub5 = Read.ReadUByte(); var ub6 = Read.ReadUByte(); var bo7 = Read.ReadBool(); var ub8 = Read.ReadUByte(); var ub9 = Read.ReadUByte(); var ub10 = Read.ReadUByte(); var ub11 = Read.ReadUByte(); var ub12 = Read.ReadUByte(); Write.WriteUByte(Code.SessionCreate); if (MainServer.CanCreateRooms && Player.CurrentRoom == null) { Room rm = new Room(Player, rs1, ub2, bo3, ub4, ub5, ub6); Write.WriteBool(true); Write.WriteUInt(rm.id); Write.WriteString(rm.name); rm.is_custom_items = bo7; rm.citm_1 = ub8; rm.citm_2 = ub9; rm.citm_3 = ub10; rm.citm_4 = ub11; rm.citm_5 = ub12; //So for special admins, we should highlight their room by making it a special tagged room. if (AdminList.isAdmin(Player.ID)) { rm.tag = 2; } Player.ListSlot.GoPlayingOnline(); } else { Write.WriteBool(false); } Write.SendTcp(buff); MainServer.Event.PlayerCreatedRoom(Player, Player.CurrentRoom); break; } //Not sent by client. case Code.UpdatePlayers: break; //Host-invoked room starting. case Code.StartRoom: { var rm = Player.CurrentRoom; if (rm == null || rm.tag == 0 || rm.players.IndexOf(Player) != 0 || rm.playstate != 1) { break; } rm.EnterVoteRoom(); break; } //A player changes his or her character in the lobby. Let the room tell the others. case Code.ChangeCharacter: { var c = Read.ReadUByte(); if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.ChangeCharacter(Player, c); MainServer.Event.PlayerChangedChar(Player, Player.Character); break; } //A player changes his or her team. Let the room tell the others. case Code.ChangeTeam: { var t = Read.ReadUByte(); if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.ChangeTeam(Player, t); MainServer.Event.PlayerChangedTeam(Player, Player.Team); break; } //The host changes these battle settings. Let their room update and then tell everyone. case Code.ChangeBattleSettings: { break; } //Not sent by client. case Code.RoomState: break; //The player requests the information of another player with this ID. case Code.PlayerInfo: { break; } //Simple packet to say that we're responding. Can be used for ping. case Code.IAmHere: { Write.WriteUByte(Code.IAmHere); Write.SendTcp(buff); break; } //The player wants a list of all open rooms. case Code.RequestRoomList: { Write.WriteUByte(Code.RequestRoomList); //Send just their IDs and a 0 at the end. The game will ask later. //The order will go like SERVER ROOMS; OPEN PLAYER ROOMS; CLOSED PLAYER ROOMS. //The extra bool reports their size (big or small). foreach (Room i in MainServer.RoomList) { if (i.visible && i.tag == 0) { Write.WriteUInt(i.id); Write.WriteBool(true); } } foreach (Room i in MainServer.RoomList) { if (i.visible && i.tag == 2 && i.playstate == 1) { Write.WriteUInt(i.id); Write.WriteBool(true); } } foreach (Room i in MainServer.RoomList) { if (i.visible && i.tag == 1 && i.playstate == 1) { Write.WriteUInt(i.id); Write.WriteBool(false); } } foreach (Room i in MainServer.RoomList) { if (i.visible && i.tag == 2 && i.playstate != 1) { Write.WriteUInt(i.id); Write.WriteBool(true); } } foreach (Room i in MainServer.RoomList) { if (i.visible && i.tag == 1 && i.playstate != 1) { Write.WriteUInt(i.id); Write.WriteBool(false); } } Write.WriteUInt(0); Write.SendTcp(buff); break; } //The player wants this specific room's information. case Code.RequestRoomInformation: { var rm = Read.ReadUInt(); var found = false; if (MainServer.RoomList.Count == 0) { break; } Write.WriteUByte(Code.RequestRoomInformation); foreach (Room i in MainServer.RoomList) { if (i.id == rm) { Write.WriteUInt(i.id); Write.WriteString(i.name); Write.WriteString(i.host_name); Write.WriteSByte(i.tag); Write.WriteUByte((byte)i.players.Count); Write.WriteUByte(i.maxplayers); Write.WriteUByte(i.mode); Write.WriteBool(i.teams); Write.WriteUByte(i.playstate); Write.WriteUByte(i.maxteams); Write.WriteUByte(i.minutes); found = true; break; } } if (found) { Write.SendTcp(buff); } else { Write.Clear(); } break; } //The player wants a list of all players. case Code.RequestPlayerList: { if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.SendPlayerList(Player); break; } //Packet echo'ing. case Code.SendMe: { Write.WriteUByte(Code.SendMe); byte DataType = Read.ReadUByte(); int val; uint uval; float valf; double vald; Write.WriteUByte(DataType); switch (DataType) { case 1: val = Read.ReadUByte(); Write.WriteUByte((byte)val); CmdSystem.AddLog(Player.Name + " echo request: " + (byte)val); break; case 2: val = Read.ReadSByte(); Write.WriteSByte((sbyte)val); CmdSystem.AddLog(Player.Name + " echo request: " + (sbyte)val); break; case 3: val = Read.ReadUShort(); Write.WriteUShort((ushort)val); CmdSystem.AddLog(Player.Name + " echo request: " + (ushort)val); break; case 4: val = Read.ReadSShort(); Write.WriteSShort((short)val); CmdSystem.AddLog(Player.Name + " echo request: " + (short)val); break; case 5: uval = Read.ReadUInt(); Write.WriteUInt(uval); CmdSystem.AddLog(Player.Name + " echo request: " + uval); break; case 6: val = (int)Read.ReadSInt(); Write.WriteSInt(val); CmdSystem.AddLog(Player.Name + " echo request: " + val); break; case 7: valf = Read.ReadFloat(); Write.WriteFloat(valf); CmdSystem.AddLog(Player.Name + " echo request: " + valf); break; case 8: vald = Read.ReadDouble(); Write.WriteDouble(vald); CmdSystem.AddLog(Player.Name + " echo request: " + vald); break; default: Read.ReadUByte(); Write.WriteUByte(0); CmdSystem.AddLog(Player.Name + " blank echo request."); break; } Write.SendTcp(Player.DataStream); break; } //A player sends a vote to his room. case Code.Vote: { byte stg = Read.ReadUByte(); if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.AcceptVote(Player, stg); break; } //The player has finished loading and is ready to start the battle. case Code.BattleReady: { if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.PlayerReady(); break; } /* * NOW, for the next few codes, the server is simply a relayer to all * the other players. It doesn't really keep any of this data, which * we should in the future so we can keep some spam/hack control. */ //The player moved, let everyone else know. case Code.Movement: { if (Player.CurrentRoom == null) { break; } var ss1 = Read.ReadSShort(); var ss2 = Read.ReadSShort(); var ub3 = Read.ReadUByte(); Write.WriteUByte(Code.Movement); Write.WriteUByte(Player.Slot); Write.WriteSShort(ss1); Write.WriteSShort(ss2); Write.WriteUByte(ub3); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //The player stopped, let everyone else know. case Code.Stopment: { if (Player.CurrentRoom == null) { break; } var ss1 = Read.ReadSShort(); var ss2 = Read.ReadSShort(); Write.WriteUByte(Code.Stopment); Write.WriteUByte(Player.Slot); Write.WriteSShort(ss1); Write.WriteSShort(ss2); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //The player used an item, let everyone else know. case Code.Item: { if (Player.CurrentRoom == null) { break; } var ub1 = Read.ReadUByte(); var bo1 = Read.ReadBool(); var ss2 = Read.ReadSShort(); var ss3 = Read.ReadSShort(); var ff4 = Read.ReadFloat(); var ff5 = Read.ReadFloat(); Write.WriteUByte(Code.Item); Write.WriteUByte(Player.Slot); Write.WriteUByte(ub1); Write.WriteBool(bo1); Write.WriteSShort(ss2); Write.WriteSShort(ss3); Write.WriteFloat(ff4); Write.WriteFloat(ff5); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } MainServer.Event.PlayerUsedItem(Player, ub1); break; } //The player got hit, let everyone else know. case Code.Hit: { if (Player.CurrentRoom == null) { break; } var ub1 = Read.ReadUByte(); var ss2 = Read.ReadSShort(); var ss3 = Read.ReadSShort(); var ff4 = Read.ReadFloat(); var ff5 = Read.ReadFloat(); var ff6 = Read.ReadFloat(); Write.WriteUByte(Code.Hit); Write.WriteUByte(Player.Slot); Write.WriteUByte(ub1); Write.WriteSShort(ss2); Write.WriteSShort(ss3); Write.WriteFloat(ff4); Write.WriteFloat(ff5); Write.WriteFloat(ff6); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } MainServer.Event.PlayerHit(Player, ub1, ff6); break; } //The player got killed, let everyone else know. case Code.Death: { if (Player.CurrentRoom == null) { break; } var ss1 = Read.ReadSShort(); var ss2 = Read.ReadSShort(); var ff3 = Read.ReadFloat(); var ub4 = Read.ReadUByte(); Write.WriteUByte(Code.Death); Write.WriteUByte(Player.Slot); Write.WriteSShort(ss1); Write.WriteSShort(ss2); Write.WriteFloat(ff3); Write.WriteUByte(ub4); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } MainServer.Event.PlayerDeath(Player, ff3); break; } //The player got a point, let everyone else know. case Code.Score: { if (Player.CurrentRoom == null) { break; } var ub1 = Read.ReadUByte(); var ub2 = Read.ReadUByte(); var ss3 = Read.ReadSShort(); Write.WriteUByte(Code.Score); Write.WriteUByte(ub1); Write.WriteUByte(ub2); Write.WriteSShort(ss3); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } MainServer.Event.PlayerScored(Player, ss3); break; } //Absolute Score Update case Code.AbsoluteScore: { if (Player.CurrentRoom == null) { break; } var ss1 = Read.ReadSShort(); Write.WriteUByte(Code.AbsoluteScore); Write.WriteUByte(Player.Slot); Write.WriteSShort(ss1); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //The player dropped coins, let everyone else know. case Code.CoinDrop: { if (Player.CurrentRoom == null) { break; } var ub1 = Read.ReadUByte(); Write.WriteUByte(Code.CoinDrop); Write.WriteUByte(Player.Slot); Write.WriteUByte(ub1); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //The player dropped coins, let everyone else know. case Code.ItemDrop: { if (Player.CurrentRoom == null) { break; } var ss1 = Read.ReadSShort(); var ss2 = Read.ReadSShort(); var fl3 = Read.ReadFloat(); var ub4 = Read.ReadUByte(); var ub5 = Read.ReadUByte(); var ub6 = Read.ReadUByte(); Write.WriteUByte(Code.ItemDrop); Write.WriteUByte(Player.Slot); Write.WriteSShort(ss1); Write.WriteSShort(ss2); Write.WriteFloat(fl3); Write.WriteUByte(ub4); Write.WriteUByte(ub5); Write.WriteUByte(ub6); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //The player's purple spawned, let everyone else know. case Code.PurpleSpawn: { if (Player.CurrentRoom == null) { break; } var ss1 = Read.ReadSShort(); var ss2 = Read.ReadSShort(); Write.WriteUByte(Code.PurpleSpawn); Write.WriteUByte(Player.Slot); Write.WriteSShort(ss1); Write.WriteSShort(ss2); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //The player has finished, here are their stats. case Code.PlayerRecap: { if (Player.Record == null || Player.CurrentRoom == null) { break; } Player.Record.HitsGiven = Read.ReadUShort(); Player.Record.Kills = Read.ReadUShort(); Player.Record.Items = Read.ReadUShort(); Player.Record.HitsTaken = Read.ReadUShort(); Player.Record.Deaths = Read.ReadUShort(); Player.Record.CoinsGained = Read.ReadUShort(); Player.Record.CoinsLost = Read.ReadUShort(); Write.WriteUByte(Code.PlayerRecap); Write.WriteUByte(Player.Slot); Player.CurrentRoom.DistributeStats(Player); break; } //The player has to send their statistics for proper attack, defense, etc. case Code.PlayerStats: { if (Player.CurrentRoom == null) { break; } var ub1 = Read.ReadUByte(); var ub2 = Read.ReadUByte(); var ub3 = Read.ReadUByte(); var ub4 = Read.ReadUByte(); Write.WriteUByte(Code.PlayerStats); Write.WriteUByte(Player.Slot); Write.WriteUByte(ub1); Write.WriteUByte(ub2); Write.WriteUByte(ub3); Write.WriteUByte(ub4); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } //They sent a Battle Complete packet and are now waiting for everyone else to finish. case Code.BattleEnd: { if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.PlayerFinished(); break; } //They pressed the Next Battle button and are waiting for everyone else to do the same. case Code.BattleComplete: { if (Player.CurrentRoom == null) { break; } Player.CurrentRoom.PlayerCompleted(); break; } //They asked for an updated Server Message pack. case Code.ServerMessages: { Write.WriteUByte(Code.ServerMessages); Write.WriteString(MainServer.GoodbyeMessage); Write.WriteString(MainServer.DCMessage); Write.WriteString(MainServer.KickMessage); Write.WriteString(MainServer.InfoMessage); Write.SendTcp(Player.DataStream); break; } //Update their XP. Simple as that. case Code.UpdateXP: { Player.XP = Read.ReadUInt(); break; } //Yes or no? case Code.CanICreateRoomsYet: { Write.WriteUByte(Code.CanICreateRoomsYet); Write.WriteBool(MainServer.CanCreateRooms); Write.SendTcp(Player.DataStream); break; } // case Code.PlayerList: { Write.WriteUByte(Code.PlayerList); foreach (PlayerListItem i in MainServer.PlayerList) { if (i.Status == Code.Status_AOnline) { Write.WriteBool(true); Write.WriteDouble(i.ID); Write.WriteUByte(i.Tag); Write.WriteUByte(i.Status); Write.WriteString(i.Name); } } foreach (PlayerListItem i in MainServer.PlayerList) { if (i.Status == Code.Status_POnline) { Write.WriteBool(true); Write.WriteDouble(i.ID); Write.WriteUByte(i.Tag); Write.WriteUByte(i.Status); Write.WriteString(i.Name); } } foreach (PlayerListItem i in MainServer.PlayerList) { if (i.Status == Code.Status_Offline) { Write.WriteBool(true); Write.WriteDouble(i.ID); Write.WriteUByte(i.Tag); Write.WriteUByte(i.Status); Write.WriteString(i.Name); } } Write.WriteBool(false); Write.SendTcp(Player.DataStream); break; } case Code.PL_Single: { var id = Read.ReadDouble(); foreach (PlayerListItem i in MainServer.PlayerList) { if (i.ID == id) { Write.WriteUByte(Code.PL_Single); Write.WriteDouble(id); Write.WriteUByte(i.Status); Write.SendTcp(Player.DataStream); } } } break; //The player dropped coins, let everyone else know. case Code.ItemInvoke: { if (Player.CurrentRoom == null) { break; } var ub1 = Read.ReadUByte(); var ss2 = Read.ReadSShort(); var ss3 = Read.ReadSShort(); Write.WriteUByte(Code.ItemInvoke); Write.WriteUByte(Player.Slot); Write.WriteUByte(ub1); Write.WriteSShort(ss2); Write.WriteSShort(ss3); foreach (TcpClientSocket Others in Player.CurrentRoom.players) { if (!Others.Equals(Player)) { Write.SendTcp(Others.DataStream); } } break; } case Code.Command: var s = Read.ReadString(); Console.WriteLine("USER INVOKED COMMAND:"); Console.WriteLine(" " + s); Console.WriteLine(" by " + Player.Name); var done = true; if (Player.Tag != 2) { done = false; CmdSystem.AddLog("User missing permissions, access denied"); } else { CmdSystem.RunCmd(s); done = CmdSystem.LastCommandSuccessful; } Write.WriteUByte(Code.Command); Write.WriteBool(done); Write.WriteString(CmdSystem.LastLog); Write.SendTcp(Player.DataStream); break; default: break; } // Back-up the read/peek position of the buffer and check for a secondary/merged packet. int myHeaderId = Player.ReadBuffer.EndRead(false); myCheck = ( byte )((myHeaderId != -1) ? myHeaderId : ~myHeaderId); } }
/// <summary> /// Send packets to a client or process data for a client independantly of reading/receiving data. /// </summary> /// <param name="myClient">Client socket class that is being handled.</param> /// <param name="myServer">Server's handle(listener) socket class.</param> public static void TcpPacketSend(TcpClientSocket myClient, TcpListenerSocket myServer) { // Send messages to a client without receiving data. }
public static void RunCmd(string myCmd) { LastCommandSuccessful = true; long RunTime = ClockTimer.GetRunTime(); string command = myCmd.ToLower(); TcpListenerSocket myTcpServer = MainServer.myTcpSocket; UdpServerSocket myUdpServer = MainServer.myUdpSocket; //Special parameter-needing commands if (command.StartsWith("setmsg welcome ")) { MainServer.WelcomeMessage = myCmd.Substring(15); MessageUpdater.SendMessagePacket(); CmdSystem.AddLog("Welcome message set to '" + MainServer.WelcomeMessage + "'"); return; } if (command.StartsWith("setmsg kick ")) { MainServer.KickMessage = myCmd.Substring(12); MessageUpdater.SendMessagePacket(); CmdSystem.AddLog("Kick message set to '" + MainServer.KickMessage + "'"); return; } if (command.StartsWith("setmsg dc ")) { MainServer.DCMessage = myCmd.Substring(10); MessageUpdater.SendMessagePacket(); CmdSystem.AddLog("Disconnected message set to '" + MainServer.DCMessage + "'"); return; } if (command.StartsWith("setmsg goodbye ")) { MainServer.GoodbyeMessage = myCmd.Substring(15); MessageUpdater.SendMessagePacket(); CmdSystem.AddLog("Disconnected message set to '" + MainServer.GoodbyeMessage + "'"); return; } if (command.StartsWith("setmsg info ")) { MainServer.InfoMessage = myCmd.Substring(12); MessageUpdater.SendMessagePacket(); CmdSystem.AddLog("Info message set to '" + MainServer.InfoMessage + "'"); return; } if (command.StartsWith("mm ")) { MessageUpdater.BroadcastMessage(myCmd.Substring(3)); CmdSystem.AddLog("BROADCASTED: " + myCmd.Substring(3)); return; } if (command.StartsWith("closeroom ")) { foreach (Room i in MainServer.RoomList) { if (i.id == Int32.Parse(myCmd.Substring(10))) { i.Dispose(); CmdSystem.AddLog("Room " + myCmd.Substring(10) + " disposed"); return; } } CmdSystem.AddLog("Could not find room " + myCmd.Substring(10)); return; } if (command.StartsWith("kick ")) { foreach (KeyValuePair <long, TcpClientSocket> i in TcpListenerSocket.ClientList) { if (i.Value.SocketId == Int32.Parse(myCmd.Substring(5))) { var Write = i.Value.WriteBuffer; Write.Clear(); Write.WriteUByte(i.Value.HeaderId); Write.WriteUByte(Code.ConnectionEnd); Write.SendTcp(i.Value.DataStream); i.Value.UserImposedDisconnection = true; i.Value.Connected = false; CmdSystem.AddLog("Player " + i.Value.Name + " has been kicked"); return; } } CmdSystem.AddLog("Could not find player with socket " + myCmd.Substring(5)); return; } if (command.StartsWith("admin ")) { foreach (KeyValuePair <long, TcpClientSocket> i in TcpListenerSocket.ClientList) { if (i.Value.ID == Int32.Parse(myCmd.Substring(6))) { if (i.Value.Tag == 2) { i.Value.Tag = 1; } else { i.Value.Tag = 2; } CmdSystem.AddLog("Player " + i.Value.Name + " admin: " + (i.Value.Tag == 2)); return; } } CmdSystem.AddLog("Could not find player with ID " + myCmd.Substring(6)); return; } //Normal commands switch (command) { case "help": Console.WriteLine("========================"); Console.WriteLine(); Console.WriteLine(" " + "help - displays list of commands"); Console.WriteLine(" " + "tcpstop - ends TCP communications"); Console.WriteLine(" " + "udpstop - ends UDP communications"); Console.WriteLine(" " + "count - counts all the TCP connections"); Console.WriteLine(" " + "status - tells how the server is doing"); Console.WriteLine(" " + "unlog - clears the log"); Console.WriteLine(" " + "clear - clears the console"); Console.WriteLine(" " + "update - force update ini file"); Console.WriteLine(); Console.WriteLine(" " + "roomlist - displays a list of all open rooms"); Console.WriteLine(" " + "players - lists all online players"); Console.WriteLine(" " + "room solo - Creates a solo play room for all modes"); Console.WriteLine(" " + "room team - Creates a team play room for all modes"); Console.WriteLine(); Console.WriteLine(" " + "clear servers - closes all server rooms"); Console.WriteLine(" " + "clear rooms - closes all rooms"); Console.WriteLine(" " + "kickall - kicks everyone off the server"); Console.WriteLine(" " + "clear pl - clears the player list"); Console.WriteLine(" " + "closeroom [roomID]"); Console.WriteLine(" " + "kick [socketID]"); Console.WriteLine(" " + "admin [playerid] - toggle admin status of this user"); Console.WriteLine(); Console.WriteLine(" " + "setmsg welcome [message]"); Console.WriteLine(" " + "setmsg goodbye [message]"); Console.WriteLine(" " + "setmsg kick [message]"); Console.WriteLine(" " + "setmsg dc [message]"); Console.WriteLine(" " + "setmsg info [message]"); Console.WriteLine(" " + "toggle makerooms - toggles player creation of rooms"); Console.WriteLine(" " + "toggle notifybots - toggles notification of tag 0 players"); Console.WriteLine(); Console.WriteLine("========================"); break; case "tcpstop": if (myTcpServer != null && myTcpServer.Status == true) { myTcpServer.Status = false; Console.WriteLine("Time(" + RunTime.ToString() + ") :: TCP Server Stopped"); } break; case "udpstop": if (myUdpServer != null && myUdpServer.Status == true) { myUdpServer.Status = false; Console.WriteLine("Time(" + RunTime.ToString() + ") :: UDP Server Stopped"); } break; case "exit": { if (myTcpServer != null && myTcpServer.Status == true) { myTcpServer.Status = false; Console.WriteLine("Time(" + RunTime.ToString() + ") :: TCP Server Stopped"); } if (myUdpServer != null && myUdpServer.Status == true) { myUdpServer.Status = false; Console.WriteLine("Time(" + RunTime.ToString() + ") :: UDP Server Stopped"); } MainServer.SettingsFile.Flush(); break; } case "status": Console.WriteLine("Time(" + RunTime.ToString() + ") :: Server Status:"); if (myTcpServer != null && myTcpServer.Status == true) { Console.WriteLine(" :: TCP Status(" + myTcpServer.Status.ToString() + ")"); } if (myUdpServer != null && myUdpServer.Status == true) { Console.WriteLine(" :: UDP Status(" + myUdpServer.Status.ToString() + ")"); } if (myTcpServer != null && myTcpServer.Status == true) { Console.WriteLine(" :: Client Count(" + TcpListenerSocket.ClientList.Count.ToString() + ")"); } break; case "unlog": CmdLog.Clear(); Console.WriteLine(RunTime.ToString() + "ms :: Log Cleared"); break; case "clear": Console.Clear(); Console.WriteLine(RunTime.ToString() + "ms :: Console Cleared"); break; case "clear pl": MainServer.PlayerList.Clear(); Console.WriteLine(RunTime.ToString() + "ms :: Player List Cleared"); break; case "update": UpdateINI.NowBackup(); Console.WriteLine(RunTime.ToString() + "ms :: INI Update Complete"); break; case "room solo": var rm = new Room(); rm.teams = false; break; case "room team": var room = new Room(); room.teams = true; break; case "players": if (TcpListenerSocket.ClientList.Count == 0) { Console.WriteLine(" No players are connected!"); break; } Console.WriteLine("Current Player List"); foreach (KeyValuePair <long, TcpClientSocket> Player in TcpListenerSocket.ClientList) { Console.WriteLine(" (" + Player.Value.SocketId + ") id:" + Player.Value.ID + " n:" + Player.Value.Name); } break; case "roomlist": if (MainServer.RoomList.Count == 0) { Console.WriteLine(" No rooms are currently open!"); break; } Console.WriteLine("Current Room List"); foreach (Room Room in MainServer.RoomList) { Console.WriteLine(" " + Room.id + ": " + Room.name + " hosted by " + Room.host_name); Console.WriteLine(" " + "Mode: " + Room.mode + " | " + "Teams: " + Room.teams + " | " + "Mins: " + Room.minutes + " | " + "MaxPlyrs: " + Room.maxplayers + " | " + "RoomState: " + Room.playstate + " | "); foreach (TcpClientSocket Player in Room.players) { Console.WriteLine(" " + Player.Slot + ". " + Player.Name + "| C: " + Player.Character + (Room.teams? " T: " + Player.Team : "")); } Console.WriteLine(); } break; case "clear rooms": try { List <Room> Rooms = new List <Room>(MainServer.RoomList); foreach (Room i in Rooms) { i.Dispose(); } CmdSystem.AddLog(" All rooms have been cleared, and players kicked out to the online lobby."); } catch { CmdSystem.AddLog(" Failed to clear roomlist."); } MainServer.RoomNumb = 0; break; case "clear servers": try { List <Room> Rooms = new List <Room>(MainServer.RoomList); foreach (Room i in Rooms) { if (i.tag == 0) { i.Dispose(); } } CmdSystem.AddLog(" All server rooms have been cleared, and their players kicked out to the main menu."); } catch { CmdSystem.AddLog(" Failed to clear."); } MainServer.RoomNumb = 0; break; case "kickall": try { foreach (KeyValuePair <long, TcpClientSocket> Player in TcpListenerSocket.ClientList) { var Write = Player.Value.WriteBuffer; Write.Clear(); Write.WriteUByte(Player.Value.HeaderId); Write.WriteUByte(Code.ConnectionEnd); Write.SendTcp(Player.Value.DataStream); Player.Value.UserImposedDisconnection = true; Player.Value.Connected = false; } CmdSystem.AddLog(" All players have been kicked."); } catch { CmdSystem.AddLog(" Kicking failed."); } break; case "toggle makerooms": MainServer.CanCreateRooms = !MainServer.CanCreateRooms; Console.WriteLine(" Player creation of rooms set to " + MainServer.CanCreateRooms + "."); break; case "toggle notifybots": MainServer.NotifyOfBots = !MainServer.NotifyOfBots; Console.WriteLine(" Bot notifications set to " + MainServer.NotifyOfBots + "."); break; default: CmdSystem.AddLog(" Unknown command"); LastCommandSuccessful = false; break; } }
/// <summary> /// Read and process packets received from the client. /// </summary> /// <param name="myClient">Client socket class that is being handled.</param> // <param name="myClientList">List of clients from the server.</param> /// <param name="myServer">Server's handle(listener) socket class.</param> // <param name="myServerSocketId">Socket ID of the server.</param> public static void TcpPacketRead(TcpClientSocket myClient, TcpListenerSocket myServer) { byte myCheck = myClient.ReadBuffer.StartRead(0); var WriteBuff = myClient.WriteBuffer; var ReadBuff = myClient.ReadBuffer; var File = MainServer.SettingsFile; var ID = myClient.PlayerID.ToString(); // Check for packets by searching for packet headers. while (myCheck == myClient.HeaderId) { byte myPacketId = ReadBuff.Readu8(); switch (myPacketId) { /* To READ from the buffer... * float myFloat = myClient.ReadBuffer.Readf32(); * int myInteger = myClient.ReadBuffer.Readu32(); * string myString = myClient.ReadBuffer.ReadStr(); * * To WRITE to the buffer and send... * myClient.WriteBuffer.SetPeek( 0 ); * myClient.WriteBuffer.Writeu8( TcpNetwork.TcpPacketHeader ); * myClient.WriteBuffer.Writeu8( 254 ); * myClient.WriteBuffer.SendTcp( myClient.DataStream );*/ //They sent this to see if the connection works. Echo their packet back. case (Code.ConnectionBegin): { //Assigns the given PlayerID to this specific client. Also the name should've given their name. myClient.PlayerID = ReadBuff.Readf64(); myClient.PlayerName = ReadBuff.ReadStr(); //Tells them that they connected. WriteBuff.SetPeek(0); WriteBuff.Writeu8(myClient.HeaderId); WriteBuff.Writeu8(Code.ConnectionBegin); WriteBuff.WriteStr(MainServer.WelcomeMessage); CmdSystem.AddLog("BBLegacy Client Connected (" + myClient.PlayerName + " [" + myClient.PlayerID.ToString() + "])"); WriteBuff.SendTcp(myClient.DataStream); //Update their online status. File.SetValue(myClient.PlayerID.ToString(), "MenuStatus", Code.Status_AOnline); File.SetValue(myClient.PlayerID.ToString(), "Name", myClient.PlayerName); break; } case (Code.ConnectionEnd): { myClient.TcpClientClose(); CmdSystem.AddLog("Client " + myClient.SocketId.ToString() + " Requested Disconnection -- Granted."); break; } case (Code.SessionCreate): { //You're actually creating a session :D //It's just like joining one, but you make it, then join. byte RoomId = 0, Failed = 0; var RoomName = ReadBuff.ReadStr(); var RoomHostName = myClient.PlayerName; //Can't make one while inside one. if (myClient.isInSession) { Failed = 1; } else { for (byte i = 0; i < 255; i++) { if (!MainServer.SessionNumberList.Contains(i)) { //Found a free room. RoomId = i; MainServer.SessionNumberList.Add(i); break; } if (i == 255) { Failed = 2; //WHAT. there's more than 250 rooms? } } } WriteBuff.SetPeek(0); WriteBuff.Writeu8(myClient.HeaderId); WriteBuff.Writeu8(Code.SessionCreate); WriteBuff.Writeu8(Failed); WriteBuff.SendTcp(myClient.DataStream); break; } case (Code.SessionJoin): { //Request to Join a Room. Which room? This room! var id = ReadBuff.Readu8(); Session RoomId = MainServer.SessionList.Find(e => e.GetID() == id); //Cannot join a room while in another. if (myClient.isInSession) { WriteBuff.SetPeek(0); WriteBuff.Writeu8(myClient.HeaderId); WriteBuff.Writeu8(Code.SessionJoin); WriteBuff.Writeu8(0); WriteBuff.SendTcp(myClient.DataStream); break; } //Success, put them in the room... myClient.isInSession = true; myClient.CurrentSession = RoomId; //...and then tell the player. WriteBuff.SetPeek(0); WriteBuff.Writeu8(myClient.HeaderId); WriteBuff.Writeu8(Code.SessionJoin); WriteBuff.Writeu8(1); WriteBuff.SendTcp(myClient.DataStream); break; } case (Code.SessionLeave): { //Request to leave the room. Which room (To tell the players in that room he left)? var RoomId = ReadBuff.Readu8(); //Cannot leave a room when you're not in one. if (!myClient.isInSession) { WriteBuff.SetPeek(0); WriteBuff.Writeu8(myClient.HeaderId); WriteBuff.Writeu8(Code.SessionLeave); WriteBuff.Writeu8(0); WriteBuff.SendTcp(myClient.DataStream); break; } //Success, take them out the room... myClient.isInSession = false; myClient.CurrentSession = null; //...and then tell the player. WriteBuff.SetPeek(0); WriteBuff.Writeu8(myClient.HeaderId); WriteBuff.Writeu8(Code.SessionJoin); WriteBuff.Writeu8(1); WriteBuff.SendTcp(myClient.DataStream); //As well as the other players in that room. Session EveryoneElse = MainServer.SessionList.Find(e => e.GetID() == RoomId); //Loop through all connected clients to see which is in the room. { foreach (KeyValuePair <long, TcpClientSocket> ClientSocket in TcpListenerSocket.ClientList) { if (ClientSocket.Value.CurrentSession == EveryoneElse) { WriteBuff.SetPeek(0); WriteBuff.Writeu8(ClientSocket.Value.HeaderId); WriteBuff.Writeu8(Code.PlayerLeave); WriteBuff.Writeu8(1); WriteBuff.SendTcp(ClientSocket.Value.DataStream); } } } //Then tell each of them that the player left. break; } default: break; } // Back-up the read/peek position of the buffer and check for a secondary/merged packet. int myHeaderId = myClient.ReadBuffer.EndRead(false); myCheck = ( byte )((myHeaderId != -1) ? myHeaderId : ~myHeaderId); } }
public static void Main() { ClockTimer.RecordRunTime(); Console.Clear(); Console.WriteLine(" ==================================================== "); Console.WriteLine(" Welcome to the BBLegacy Dedicated Server [prototype] "); Console.WriteLine(); Console.WriteLine(" INIFile Management Code by S.T.A. snc (C)2009-2013 "); Console.WriteLine(" Networking System by FatalSleep from the GMCommunity "); Console.WriteLine(" ==================================================== "); Console.WriteLine(); //Fetch the External IP Address, if they're not using local. if (IsLocal) { TheIPAddress = "127.0.0.1"; } else { Console.WriteLine("Fetching IP Address... "); TheIPAddress = getExternalIp(); Console.WriteLine(" " + TheIPAddress + ", LAN " + getInternalIP()); } Console.WriteLine("Loading player database..."); new UpdateINI(3600000); MessageUpdate = new MessageUpdater(120000); Event = new Automation(); var tmp = 1; while (tmp <= SettingsFile.GetValue("Server Configuration", "NumberOfPlayers", 1)) { PlayerListItem tmpp = new PlayerListItem(); tmpp.ID = SettingsFile.GetValue("PlayerListItem" + tmp, "ID", 0.00); tmpp.Name = SettingsFile.GetValue("PlayerListItem" + tmp, "Name", "{NULL}"); tmpp.Tag = (byte)SettingsFile.GetValue("PlayerListItem" + tmp, "Tag", 0); Console.WriteLine(" PL" + tmpp.ID + " " + tmpp.Name + " (" + tmpp.Tag + ")"); tmp++; if (tmpp.Tag == 0) { tmpp.Automate(); } } Console.WriteLine("done."); myTcpSocket = new TcpListenerSocket(TheIPAddress, Port, MaxClients, ReadSize, WriteSize, Alignment, PacketHeader); myUdpSocket = new UdpServerSocket(Port, ReadSize, WriteSize, Alignment, PacketHeader); Console.WriteLine("UDP Connection Listener Established (" + TheIPAddress + " :: " + Port + ")"); string Command = ""; if (!CanCreateRooms) { Console.WriteLine("WARNING: Player creation of rooms is disabled. You MUST use room creation commands in order for them to play on your server!"); } Thread.Sleep(2000); Console.WriteLine("You can now type 'help' for some commands."); Console.WriteLine(); Console.WriteLine(" ==================================================== "); while (myTcpSocket.Status == true || myUdpSocket.Status == true) { try { Command = Console.ReadLine(); CmdSystem.RunCmd(Command); } catch (Exception e) { CmdSystem.AddLog("UNCAUGHT EXCEPTION: " + e.GetType() + " :: " + e.Message); CmdSystem.AddLog("Stack Trace: "); Console.WriteLine(); Console.WriteLine(e.StackTrace); Console.WriteLine(); } } ClockTimer.StopRunTime(); }