//Method to delete character from player's account public static void DeleteCharacter(int serverid, Session MySession) { //Opens new Sql connection using connection parameters var connectionString = ConfigurationManager.ConnectionStrings["DevLocal"].ConnectionString; //Set connection property from connection string and open connection using MySqlConnection con = new MySqlConnection(connectionString); con.Open(); //Creates var to store a MySQlcommand with the query and connection parameters. using var cmd = new MySqlCommand("DeleteCharacter", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("cServerID", serverid); //Executes a reader on the previous var. using MySqlDataReader rdr = cmd.ExecuteReader(); //Log which character serverid was deleted Logger.Info($"Deleted Character with ServerID: {serverid}"); //Create a new list of characters after deletion List <Character> MyCharacterList = new List <Character>(); MyCharacterList = SQLOperations.AccountCharacters(MySession); //Send Fresh Character Listing ProcessOpcode.CreateCharacterList(MyCharacterList, MySession); }
public static void ProcessMessageBundle(Session MySession, List <byte> MyPacket) { ///Need to consider how many messages could be in here, and message types ///FB/FA/40/F9 /// while (MyPacket.Count() > 0) { ///Get our Message Type ushort MessageTypeOpcode = GrabOpcode(MyPacket); switch (MessageTypeOpcode) { //General opcodes (0xFB, 0xF9's) case MessageOpcodeTypes.ShortReliableMessage: case MessageOpcodeTypes.LongReliableMessage: case MessageOpcodeTypes.UnknownMessage: ///Work on processing this opcode ProcessOpcode.ProcessOpcodes(MySession, MessageTypeOpcode, MyPacket); break; //Client Actor update (0x4029's) case UnreliableTypes.ClientActorUpdate: ProcessUnreliable.ProcessUnreliables(MySession, MessageTypeOpcode, MyPacket); break; default: //Shouldn't get here? Console.WriteLine($"Received unknown Message: {MessageTypeOpcode}"); //Should we consume the whole message here if it is unknown so we can keep processing? break; } } MySession.RdpReport = true; MySession.ClientFirstConnect = true; //Reset ack timer MySession.ResetTimer(); Logger.Info("Done processing messages in packet"); ///Should we just initiate responses to clients through here for now? ///Ultimately we want to have a seperate thread with a server tick, ///that may handle initiating sending messages at timed intervals, and initiating data collection such as C9's }
///When server creates internal master sessions, key difference is AccountID atm.... Maybe need to be more complicated eventually public Session(ushort clientEndpoint, IPEndPoint MyIPEndPoint, int AccountID) ///public Session(ushort clientEndpoint, ushort RemoteMaster, ushort SessionPhase, uint SessionIDBase, uint SessionIDUp, uint AccountID) { Logger.Info("Creating Master Session"); this.ClientEndpoint = clientEndpoint; this.RemoteMaster = true; this.MyIPEndPoint = MyIPEndPoint; ///Need to perform some leg work here to create this internal master session this.SessionIDBase = DNP3Creation.DNP3Session(); ///This will now relate to Our ingame character ID. When we first create our master session, (character ingame ID / 2) - 1 should be our IDUp ///Once we start memory dump, IDUp + 1's to be half ingame ID this.SessionIDUp = SessionManager.ObtainIDUp() - 1; this._AccountID = AccountID; ///We don't need to ack a session this Time, we do however need client to ack our's, should this be tracked? this.SessionAck = true; this.CharacterSelect = true; ///Trigger contact with client inside session ProcessOpcode.GenerateClientContact(this); StartTimer(2000); }
//Method to create new character for player's account public static void CreateCharacter(Session MySession, Character charCreation) { //Instantiate new list of Characters to return new character listing //Local variables to get string values to store in the DB from dictionary keys received from client string humType = charCreation.HumTypeDict[charCreation.HumTypeNum]; string classType = charCreation.CharClassDict[charCreation.StartingClass]; string raceType = charCreation.CharRaceDict[charCreation.Race]; string sexType = charCreation.CharSexDict[charCreation.Gender]; //Calculate total TP used among all stats for DB storage int UsedTP = charCreation.AddStrength + charCreation.AddStamina + charCreation.AddAgility + charCreation.AddDexterity + charCreation.AddWisdom + charCreation.AddIntelligence + charCreation.AddCharisma; //Create and Open new Sql connection using connection parameters var connectionString = ConfigurationManager.ConnectionStrings["DevLocal"].ConnectionString; //Set connection property from connection string and open connection using MySqlConnection con = new MySqlConnection(connectionString); con.Open(); //Assign query string and connection to commands using var cmd = new MySqlCommand("GetCharModel", con); cmd.CommandType = CommandType.StoredProcedure; //Add parameter values for parameterized string. cmd.Parameters.AddWithValue("@RaceType", raceType); cmd.Parameters.AddWithValue("@ClassType", classType); cmd.Parameters.AddWithValue("@HumType", humType); cmd.Parameters.AddWithValue("@SexType", sexType); //Execute reader on SQL command using MySqlDataReader rdr = cmd.ExecuteReader(); //Iterate through default character values for class and race and assign to new character while (rdr.Read()) { charCreation.Tunar = rdr.GetInt32(5); charCreation.UnusedTP = rdr.GetInt32(7); charCreation.TotalAssignableTP = rdr.GetInt32(8); charCreation.XCoord = rdr.GetFloat(9); charCreation.YCoord = rdr.GetFloat(10); charCreation.ZCoord = rdr.GetFloat(11); charCreation.Facing = rdr.GetFloat(12); charCreation.DefaultStrength = rdr.GetInt32(14); charCreation.DefaultStamina = rdr.GetInt32(15); charCreation.DefaultAgility = rdr.GetInt32(16); charCreation.DefaultDexterity = rdr.GetInt32(17); charCreation.DefaultWisdom = rdr.GetInt32(18); charCreation.DefaultIntelligence = rdr.GetInt32(19); charCreation.DefaultCharisma = rdr.GetInt32(20); charCreation.ModelID = rdr.GetInt32(21); } rdr.Close(); con.Close(); //Calculate Unused TP still available to character upon entering world. charCreation.UnusedTP = charCreation.UnusedTP - UsedTP; //Add total strength from default plus added TP to each category. Not sure this is correct, may need to still add the TP from client charCreation.Strength = charCreation.DefaultStrength + charCreation.AddStrength; charCreation.Stamina = charCreation.DefaultStamina + charCreation.AddStamina; charCreation.Agility = charCreation.DefaultAgility + charCreation.AddAgility; charCreation.Dexterity = charCreation.DefaultDexterity + charCreation.AddDexterity; charCreation.Wisdom = charCreation.DefaultWisdom + charCreation.AddWisdom; charCreation.Intelligence = charCreation.DefaultIntelligence + charCreation.AddIntelligence; charCreation.Charisma = charCreation.DefaultCharisma + charCreation.AddCharisma; //Open second connection using query string params //Set connection property from connection string and open connection using MySqlConnection SecondCon = new MySqlConnection(connectionString); SecondCon.Open(); //Create second command using second connection and char insert query string using var SecondCmd = new MySqlCommand("CreateCharacter", SecondCon); SecondCmd.CommandType = CommandType.StoredProcedure; //Add all character attributes for new character creation to parameterized values SecondCmd.Parameters.AddWithValue("@charName", charCreation.CharName); //Needs to be MySession.AccountID once CharacterSelect shows characters off true AccountID. SecondCmd.Parameters.AddWithValue("AccountID", MySession.AccountID); SecondCmd.Parameters.AddWithValue("ModelID", charCreation.ModelID); SecondCmd.Parameters.AddWithValue("TClass", charCreation.StartingClass); SecondCmd.Parameters.AddWithValue("Race", charCreation.Race); SecondCmd.Parameters.AddWithValue("HumType", humType); SecondCmd.Parameters.AddWithValue("Level", charCreation.Level); SecondCmd.Parameters.AddWithValue("HairColor", charCreation.HairColor); SecondCmd.Parameters.AddWithValue("HairLength", charCreation.HairLength); SecondCmd.Parameters.AddWithValue("HairStyle", charCreation.HairStyle); SecondCmd.Parameters.AddWithValue("FaceOption", charCreation.FaceOption); SecondCmd.Parameters.AddWithValue("classIcon", charCreation.StartingClass); //May need other default values but these hard set values are placeholders for now SecondCmd.Parameters.AddWithValue("TotalXP", 0); SecondCmd.Parameters.AddWithValue("Debt", 0); SecondCmd.Parameters.AddWithValue("Breath", 255); SecondCmd.Parameters.AddWithValue("Tunar", charCreation.Tunar); SecondCmd.Parameters.AddWithValue("BankTunar", charCreation.BankTunar); SecondCmd.Parameters.AddWithValue("UnusedTP", charCreation.UnusedTP); SecondCmd.Parameters.AddWithValue("TotalTP", 350); SecondCmd.Parameters.AddWithValue("X", charCreation.XCoord); SecondCmd.Parameters.AddWithValue("Y", charCreation.YCoord); SecondCmd.Parameters.AddWithValue("Z", charCreation.ZCoord); SecondCmd.Parameters.AddWithValue("Facing", charCreation.Facing); SecondCmd.Parameters.AddWithValue("Strength", charCreation.Strength); SecondCmd.Parameters.AddWithValue("Stamina", charCreation.Stamina); SecondCmd.Parameters.AddWithValue("Agility", charCreation.Agility); SecondCmd.Parameters.AddWithValue("Dexterity", charCreation.Dexterity); SecondCmd.Parameters.AddWithValue("Wisdom", charCreation.Wisdom); SecondCmd.Parameters.AddWithValue("Intelligence", charCreation.Intelligence); SecondCmd.Parameters.AddWithValue("Charisma", charCreation.Charisma); //May need other default or calculated values but these hard set values are placeholders for now SecondCmd.Parameters.AddWithValue("CurrentHP", 1000); SecondCmd.Parameters.AddWithValue("MaxHP", 1000); SecondCmd.Parameters.AddWithValue("CurrentPower", 500); SecondCmd.Parameters.AddWithValue("MaxPower", 500); SecondCmd.Parameters.AddWithValue("Healot", 20); SecondCmd.Parameters.AddWithValue("Powerot", 10); SecondCmd.Parameters.AddWithValue("Ac", 0); SecondCmd.Parameters.AddWithValue("PoisonR", 10); SecondCmd.Parameters.AddWithValue("DiseaseR", 10); SecondCmd.Parameters.AddWithValue("FireR", 10); SecondCmd.Parameters.AddWithValue("ColdR", 10); SecondCmd.Parameters.AddWithValue("LightningR", 10); SecondCmd.Parameters.AddWithValue("ArcaneR", 10); SecondCmd.Parameters.AddWithValue("Fishing", 0); SecondCmd.Parameters.AddWithValue("Base_Strength", charCreation.DefaultStrength); SecondCmd.Parameters.AddWithValue("Base_Stamina", charCreation.DefaultStamina); SecondCmd.Parameters.AddWithValue("Base_Agility", charCreation.DefaultAgility); SecondCmd.Parameters.AddWithValue("Base_Dexterity", charCreation.DefaultDexterity); SecondCmd.Parameters.AddWithValue("Base_Wisdom", charCreation.DefaultWisdom); SecondCmd.Parameters.AddWithValue("Base_Intelligence", charCreation.DefaultIntelligence); SecondCmd.Parameters.AddWithValue("Base_Charisma", charCreation.DefaultCharisma); //See above comments regarding hard set values SecondCmd.Parameters.AddWithValue("CurrentHP2", 1000); SecondCmd.Parameters.AddWithValue("BaseHP", 1000); SecondCmd.Parameters.AddWithValue("CurrentPower2", 500); SecondCmd.Parameters.AddWithValue("BasePower", 500); SecondCmd.Parameters.AddWithValue("Healot2", 20); SecondCmd.Parameters.AddWithValue("Powerot2", 10); //Execute parameterized statement entering it into the DB //using MySqlDataReader SecondRdr = SecondCmd.ExecuteReader(); SecondCmd.ExecuteNonQuery(); SecondCon.Close(); ///Close DB connection SecondCon.Close(); //Log which character serverid was created Console.WriteLine($"Created Character with Name: {charCreation.CharName}"); List <Character> MyCharacterList = new List <Character>(); MyCharacterList = SQLOperations.AccountCharacters(MySession); //Send Fresh Character Listing ProcessOpcode.CreateCharacterList(MyCharacterList, MySession); }
private static void ProcessRdpReport(Session MySession, List <byte> MyPacket, bool UnreliableReport) { //Eventually incorporate UnreliableReport to cycle through unreliables and update accordingly //Read client bundle here. Accept client bundle as is because packets could be lost or dropped, client bundle# should not be "tracked" //considerations could be to track it for possible drop/lost rates MySession.clientBundleNumber = (ushort)(MyPacket[1] << 8 | MyPacket[0]); ushort LastRecvBundleNumber = (ushort)(MyPacket[3] << 8 | MyPacket[2]); ushort LastRecvMessageNumber = (ushort)(MyPacket[5] << 8 | MyPacket[4]); //Check our list of reliable messages to remove for (int i = 0; i < MySession.MyMessageList.Count(); i++) { //If our message stored is less then client ack, need to remove it! if (MySession.MyMessageList[i - i].ThisMessagenumber <= LastRecvMessageNumber) { MySession.MyMessageList.RemoveAt(0); } //Need to keep remaining messages, move on else { break; } } MyPacket.RemoveRange(0, 6); ///Only one that really matters, should tie into our packet resender stuff if (MySession.serverMessageNumber >= LastRecvMessageNumber) { ///This should be removing messages from resend mechanics. ///Update our last known message ack'd by client MySession.clientRecvMessageNumber = LastRecvMessageNumber; } ///Triggers creating master session if (((MySession.clientEndpoint + 1) == (MySession.sessionIDBase & 0x0000FFFF)) && MySession.SessionAck && MySession.serverSelect == false) { ///Key point here for character select is (MySession.clientEndpoint + 1 == MySession.sessionIDBase) ///SessionIDBase is 1 more then clientEndPoint ///Assume it's Create Master session? Session NewMasterSession = new Session(MySession.clientEndpoint, MySession.MyIPEndPoint, MySession.AccountID); SessionManager.AddMasterSession(NewMasterSession); } ///Trigger Server Select with this? else if ((MySession.clientEndpoint == (MySession.sessionIDBase & 0x0000FFFF)) && MySession.SessionAck && MySession.serverSelect == false) { MySession.serverSelect = true; } ///Triggers Character select else if (MySession.CharacterSelect && (MySession.clientEndpoint != MySession.sessionIDBase)) { MySession.CharacterSelect = false; List <Character> MyCharacterList = new List <Character>(); Logger.Info("Generating Character Select"); MyCharacterList = SQLOperations.AccountCharacters(MySession); //Assign to our session MySession.CharacterData = MyCharacterList; ProcessOpcode.CreateCharacterList(MyCharacterList, MySession); } else if (MySession.Dumpstarted) { //Let client know more data is coming if (MySession.MyDumpData.Count() > 500) { List <byte> ThisChunk = MySession.MyDumpData.GetRange(0, 500); MySession.MyDumpData.RemoveRange(0, 500); ///Handles packing message into outgoing packet RdpCommOut.PackMessage(MySession, ThisChunk, MessageOpcodeTypes.MultiShortReliableMessage); } //End of dump else { List <byte> ThisChunk = MySession.MyDumpData.GetRange(0, MySession.MyDumpData.Count()); MySession.MyDumpData.Clear(); ///Handles packing message into outgoing packet RdpCommOut.PackMessage(MySession, ThisChunk, MessageOpcodeTypes.ShortReliableMessage); //turn dump off MySession.Dumpstarted = false; //Gather remaining data to send in dump //ignore list ProcessOpcode.IgnoreList(MySession); //Randommessage //RandomFriend //characterSpeed ProcessOpcode.ActorSpeed(MySession); //Some opcode } } else { Logger.Err($"Client received server message {LastRecvMessageNumber}, expected {MySession.serverMessageNumber}"); } }