private static void ProcessDelChar(Session MySession, List <byte> myPacket) { //Passes in packet with ServerID on it, will grab, transform and return ServerID while also removing packet bytes int clientServID = (int)Utility_Funcs.Untechnique(myPacket); //Call SQL delete method to actually process the delete. SQLOperations.DeleteCharacter(clientServID, MySession); }
///When a new session is identified, we add this into our endpoint/session list public static void ProcessSession(List <byte> myPacket, IPEndPoint MyIPEndPoint, ushort ClientEndpoint) ///public static void ProcessSession(List<byte> myPacket, bool NewSession) { bool RemoteEndPoint = false; bool NewInstance = false; bool InstanceHeader = false; bool ResetInstance = false; uint val = Utility_Funcs.Unpack(myPacket); //Get's this bundle length int BundleLength = (int)(val & 0x7FF); int value = (int)(val - (val & 0x7FF)); if ((value & 0x80000) != 0) //Requesting instance ack, starting a new session/instance from client { NewInstance = true; } if ((value & 0x02000) != 0) //Has instance in header { InstanceHeader = true; } if ((value & 0x10000) != 0) // reset connection? { ResetInstance = true; } if ((value & 0x0800) != 0) { RemoteEndPoint = true; } //if false, means 4 byte instance header has been removed and only need to read the 3 byte character ID (If server is master //If client is "master", then goes straight into bundle type if (InstanceHeader) { uint SessionIDBase = (uint)(myPacket[3] << 24 | myPacket[2] << 16 | myPacket[1] << 8 | myPacket[0]); myPacket.RemoveRange(0, 4); //If not reset instance, start processing packet data if (ResetInstance) { //Try to find the instance try { ///This finds our session by utilizing endpoints and IPEndPoint info (IP and Port) and drops it DropSession(SessionList.Find(i => Equals(i.clientEndpoint, ClientEndpoint) && Equals(i.MyIPEndPoint, MyIPEndPoint) && Equals(i.sessionIDBase, SessionIDBase))); //Remove the double session information myPacket.RemoveRange(0, 4); if (RemoteEndPoint) { //Remove the 3 byte "Object ID" myPacket.RemoveRange(0, 3); } //if mutliple bundles, process next one if (myPacket.Count() > 10) { //Process next bundle ProcessSession(myPacket, MyIPEndPoint, ClientEndpoint); } } catch { //Just let it die gracefully if not in list // possible for a session to not be in the list if a new connection } } //If new instance, client is initiating this and we know bytes to read else if (NewInstance) { Logger.Info("Checking if session \"exists\""); bool SessionExistence = SessionList.Exists(i => Equals(i.clientEndpoint, ClientEndpoint) && Equals(i.MyIPEndPoint, MyIPEndPoint) && Equals(i.sessionIDBase, SessionIDBase)); ///If it exists, returns to drop this request if (SessionExistence) { ///This "drops" the packet ///If a client from x IPAddress tries to connect with the same endpoint and IP ///and we will drop and wait for clients next endpoint ///Client will do the leg work to "remove" the session return; } ///Create the session Logger.Info("Creating new session for Client"); ///Create our session object instance Session thisSession = new Session(ClientEndpoint, MyIPEndPoint, SessionIDBase); ///Add this sesison to our session list AddMasterSession(thisSession); //Process remaining data ProcessSession(thisSession, myPacket); } //Continue processing session else { //Grab session Session thisSession = SessionList.Find(i => Equals(i.clientEndpoint, ClientEndpoint) && Equals(i.MyIPEndPoint, MyIPEndPoint) && Equals(i.sessionIDBase, SessionIDBase)); if (thisSession == null) { Console.WriteLine("Error Finding Session, maybe transition to memory dump? Ignore for now"); return; } //If server is master/initiated the session we need to remove the 3 byte session Identifier from packet if (thisSession.remoteMaster) { //Could always do an additional check to make sure this matches internally? //Something like //if (thisSession.SessionIDUp == Utility_Funcs.Untechnique(myPacket)) //{//Continue} //else{ //Note exception and fail gracefully?} //Will read our Session Identifier and remove it off the packet for us int SessionIDUp = Utility_Funcs.Untechnique(myPacket); } //If remote master is 0, doesn't really matter... means client is "master" and will not have the 3 byte characterInstanceID ProcessSession(thisSession, myPacket); } } //4 byte header has been removed else { //Assumption would be this must be an ongoing session, so should never expect a new session without the instance header //Grab session //Will this always be correct? Shouldn't have duplicate client endpoints so should be... Session thisSession = SessionList.Find(i => Equals(i.clientEndpoint, ClientEndpoint) && Equals(i.MyIPEndPoint, MyIPEndPoint)); //If server is master/initiated the session we need to remove the 3 byte session Identifier from packet if (thisSession.remoteMaster) { //Could always do an additional check to make sure this matches internally? //Something like //if (thisSession.SessionIDUp == Utility_Funcs.Untechnique(myPacket)) //{//Continue} //else{ //Note exception and fail gracefully?} //Will read our Session Identifier and remove it off the packet for us int SessionIDUp = Utility_Funcs.Untechnique(myPacket); } //If remote master is 0, doesn't really matter... means client is "master" and will not have the 3 byte characterInstanceID ProcessSession(thisSession, myPacket); } }
//Method to create new character when new character opcode is received private static void ProcessCreateChar(Session MySession, List <byte> myPacket) { //Create NewCharacter object Character charCreation = new Character(); //Log that a new character creation packet was received Logger.Info("Received Character Creation Packet"); //Get length of characters name expected in packet int nameLength = myPacket[3] << 24 | myPacket[2] << 16 | myPacket[1] << 8 | myPacket[0]; //Remove nameLength from packet myPacket.RemoveRange(0, 4); //var for actual character name byte[] characterNameArray = new byte[nameLength]; //Copy the actual character name to above variable myPacket.CopyTo(0, characterNameArray, 0, nameLength); //Remove charactername from packet myPacket.RemoveRange(0, nameLength); //Make charactername readable charCreation.CharName = Encoding.Default.GetString(characterNameArray); //Before processing a full character creation check if the characters name already exists in the DB. //Later this will need to include a character/world combination if additional servers are spun up. if (charCreation.CharName == SQLOperations.CheckName(charCreation.CharName)) { myPacket.Clear(); //List and assignment to hold game op code in bytes to send out List <byte> NameTaken = new List <byte>(); NameTaken.AddRange(BitConverter.GetBytes(GameOpcode.NameTaken)); //Log character name taken and send out RDP message to pop up that name is taken. Console.WriteLine("Character Name Already Taken"); RdpCommOut.PackMessage(MySession, MessageOpcodeTypes.ShortReliableMessage, GameOpcode.NameTaken); } //If name not found continue to actually create character else { //Get starting level charCreation.Level = Utility_Funcs.Untechnique(myPacket); //Divide startLevel by 2 because client doubles it //Get single byte attributes charCreation.Race = Utility_Funcs.Untechnique(myPacket); charCreation.StartingClass = Utility_Funcs.Untechnique(myPacket); charCreation.Gender = Utility_Funcs.Untechnique(myPacket); charCreation.HairColor = Utility_Funcs.Untechnique(myPacket); charCreation.HairLength = Utility_Funcs.Untechnique(myPacket); charCreation.HairStyle = Utility_Funcs.Untechnique(myPacket); charCreation.FaceOption = Utility_Funcs.Untechnique(myPacket); charCreation.HumTypeNum = Utility_Funcs.Untechnique(myPacket); //Get player attributes from packet and remove bytes after reading into variable charCreation.AddStrength = myPacket[3] << 24 | myPacket[2] << 16 | myPacket[1] << 8 | myPacket[0]; charCreation.AddStamina = myPacket[7] << 24 | myPacket[6] << 16 | myPacket[5] << 8 | myPacket[4]; charCreation.AddAgility = myPacket[11] << 24 | myPacket[10] << 16 | myPacket[9] << 8 | myPacket[8]; charCreation.AddDexterity = myPacket[15] << 24 | myPacket[14] << 16 | myPacket[13] << 8 | myPacket[12]; charCreation.AddWisdom = myPacket[19] << 24 | myPacket[18] << 16 | myPacket[17] << 8 | myPacket[16]; charCreation.AddIntelligence = myPacket[23] << 24 | myPacket[22] << 16 | myPacket[21] << 8 | myPacket[20]; charCreation.AddCharisma = myPacket[27] << 24 | myPacket[26] << 16 | myPacket[25] << 8 | myPacket[24]; myPacket.RemoveRange(0, 28); //Call SQL method for character creation SQLOperations.CreateCharacter(MySession, charCreation); } }