diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 54511e3a..dddeea59 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -1,5 +1,4 @@ -using FFXIVClassic_Lobby_Server.dataobjects; -using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient; using Dapper; using Newtonsoft.Json; using System; @@ -8,14 +7,21 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using FFXIVClassic_Lobby_Server.common; -using FFXIVClassic_Map_Server.dataobjects.database; using FFXIVClassic_Map_Server.dataobjects.chara.npc; +using FFXIVClassic_Map_Server.dataobjects.chara; +using FFXIVClassic_Map_Server.utils; +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.packets.send.player; +using FFXIVClassic_Lobby_Server.dataobjects; +using FFXIVClassic_Map_Server; +using FFXIVClassic_Map_Server.common.EfficientHashTables; namespace FFXIVClassic_Lobby_Server { class Database { + public static uint getUserIdFromSession(String sessionId) { uint id = 0; @@ -66,76 +72,6 @@ namespace FFXIVClassic_Lobby_Server } } - public static DBCharacter getCharacter(uint charId) - { - using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) - { - DBCharacter chara = null; - try - { - conn.Open(); - chara = conn.Query("SELECT * FROM characters WHERE id=@CharaId", new { CharaId = charId }).SingleOrDefault(); - } - catch (MySqlException e) - { - } - finally - { - conn.Dispose(); - } - - return chara; - } - } - - public static DBAppearance getAppearance(bool loadFromPlayerTable, uint charaId) - { - using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) - { - DBAppearance appearance = null; - try - { - conn.Open(); - - if (loadFromPlayerTable) - appearance = conn.Query("SELECT * FROM characters_appearance WHERE characterId=@CharaId", new { CharaId = charaId }).SingleOrDefault(); - else - appearance = conn.Query("SELECT * FROM npc_appearance WHERE npcId=@CharaId", new { CharaId = charaId }).SingleOrDefault(); - } - catch (MySqlException e) - { - } - finally - { - conn.Dispose(); - } - - return appearance; - } - } - - public static DBStats getCharacterStats(uint charaId) - { - using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) - { - DBStats stats = null; - try - { - conn.Open(); - stats = conn.Query("SELECT * FROM characters_stats WHERE characterId=@CharaId", new { CharaId = charaId }).SingleOrDefault(); - } - catch (MySqlException e) - { - } - finally - { - conn.Dispose(); - } - - return stats; - } - } - public static List getNpcList() { using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) @@ -158,5 +94,500 @@ namespace FFXIVClassic_Lobby_Server } } + public static void loadPlayerCharacter(Player player) + { + string query; + MySqlCommand cmd; + + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load basic info + query = @" + SELECT + name, + positionX, + positionY, + positionZ, + rotation, + actorState, + currentZoneId, + currentClassJob, + gcCurrent, + gcLimsaRank, + gcGridaniaRank, + gcUldahRank, + currentTitle, + guardian, + birthDay, + birthMonth, + initialTown, + tribe, + currentParty, + restBonus, + achievementPoints + FROM characters WHERE id = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + player.displayNameId = 0xFFFFFFFF; + player.customDisplayName = reader.GetString(0); + player.oldPositionX = player.positionX = reader.GetFloat(1); + player.oldPositionY = player.positionY = reader.GetFloat(2); + player.oldPositionZ = player.positionZ = reader.GetFloat(3); + player.oldRotation = player.rotation = reader.GetFloat(4); + player.currentMainState = reader.GetUInt16(5); + player.zoneId = reader.GetUInt32(6); + player.charaWork.parameterSave.state_mainSkill[0] = reader.GetByte(7); + player.gcCurrent = reader.GetByte(8); + player.gcRankLimsa = reader.GetByte(9); + player.gcRankGridania = reader.GetByte(10); + player.gcRankUldah = reader.GetByte(11); + player.currentTitle = reader.GetUInt32(12); + player.playerWork.guardian = reader.GetByte(13); + player.playerWork.birthdayDay = reader.GetByte(14); + player.playerWork.birthdayMonth = reader.GetByte(15); + player.playerWork.initialTown = reader.GetByte(16); + player.playerWork.tribe = reader.GetByte(17); + player.playerWork.restBonusExpRate = reader.GetInt32(19); + player.achievementPoints = reader.GetUInt32(20); + } + } + + player.charaWork.parameterSave.state_mainSkillLevel = 49; + + /* + //Get level of our classjob + //Load appearance + query = @" + SELECT + baseId + FROM characters_appearance WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + + } + + } + */ + + //Get level of our classjob + //Load appearance + query = @" + SELECT + hp, + hpMax, + mp, + mpMax + FROM characters_parametersave WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + player.charaWork.parameterSave.hp[0] = reader.GetInt16(0); + player.charaWork.parameterSave.hpMax[0] = reader.GetInt16(1); + player.charaWork.parameterSave.mp = reader.GetInt16(2); + player.charaWork.parameterSave.mpMax = reader.GetInt16(3); + } + } + + //Load appearance + query = @" + SELECT + baseId, + size, + voice, + skinColor, + hairStyle, + hairColor, + hairHighlightColor, + eyeColor, + characteristics, + characteristicsColor, + faceType, + ears, + faceMouth, + faceFeatures, + faceNose, + faceEyeShape, + faceIrisSize, + faceEyebrows, + mainHand, + offHand, + head, + body, + hands, + legs, + feet, + waist, + leftFinger, + rightFinger, + leftEars, + rightEars + FROM characters_appearance WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + if (reader.GetUInt32(0) == 0xFFFFFFFF) + player.modelId = CharacterUtils.getTribeModel(player.playerWork.tribe); + else + player.modelId = reader.GetUInt32(0); + player.appearanceIds[Character.SIZE] = reader.GetByte(1); + player.appearanceIds[Character.COLORINFO] = (uint)(reader.GetUInt16(3) | (reader.GetUInt16(5) << 10) | (reader.GetUInt16(7) << 20)); + player.appearanceIds[Character.FACEINFO] = PrimitiveConversion.ToUInt32(CharacterUtils.getFaceInfo(reader.GetByte(8), reader.GetByte(9), reader.GetByte(10), reader.GetByte(11), reader.GetByte(12), reader.GetByte(13), reader.GetByte(14), reader.GetByte(15), reader.GetByte(16), reader.GetByte(17))); + player.appearanceIds[Character.HIGHLIGHT_HAIR] = (uint)(reader.GetUInt16(6) | reader.GetUInt16(4) << 10); + player.appearanceIds[Character.VOICE] = reader.GetByte(2); + player.appearanceIds[Character.WEAPON1] = reader.GetUInt32(18); + player.appearanceIds[Character.WEAPON2] = reader.GetUInt32(19); + player.appearanceIds[Character.HEADGEAR] = reader.GetUInt32(20); + player.appearanceIds[Character.BODYGEAR] = reader.GetUInt32(21); + player.appearanceIds[Character.LEGSGEAR] = reader.GetUInt32(22); + player.appearanceIds[Character.HANDSGEAR] = reader.GetUInt32(23); + player.appearanceIds[Character.FEETGEAR] = reader.GetUInt32(24); + player.appearanceIds[Character.WAISTGEAR] = reader.GetUInt32(25); + player.appearanceIds[Character.R_EAR] = reader.GetUInt32(26); + player.appearanceIds[Character.L_EAR] = reader.GetUInt32(27); + player.appearanceIds[Character.R_FINGER] = reader.GetUInt32(28); + player.appearanceIds[Character.L_FINGER] = reader.GetUInt32(29); + } + + } + + //Load Status Effects + query = @" + SELECT + statusId, + expireTime + FROM characters_statuseffect WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + int count = 0; + while (reader.Read()) + { + player.charaWork.status[count] = reader.GetUInt16(0); + player.charaWork.statusShownTime[count] = reader.GetUInt32(1); + } + } + + //Load Chocobo + query = @" + SELECT + hasChocobo, + hasGoobbue, + chocoboAppearance, + chocoboName + FROM characters_chocobo WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + player.hasChocobo = reader.GetBoolean(0); + player.hasGoobbue = reader.GetBoolean(1); + player.chocoboAppearance = reader.GetByte(2); + player.chocoboName = reader.GetString(3); + } + } + + //Load Timers + query = @" + SELECT + thousandmaws, + dzemaeldarkhold, + bowlofembers_hard, + bowlofembers, + thornmarch, + aurumvale, + cutterscry, + battle_aleport, + battle_hyrstmill, + battle_goldenbazaar, + howlingeye_hard, + howlingeye, + castrumnovum, + bowlofembers_extreme, + rivenroad, + rivenroad_hard, + behests, + companybehests, + returntimer, + skirmish + FROM characters_timers WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + for (int i = 0; i < player.timers.Length; i++) + player.timers[i] = reader.GetUInt32(i); + } + } + + //Load Hotbar + query = @" + SELECT + hotbarSlot, + commandId, + recastTime + FROM characters_hotbar WHERE characterId = @charId AND classId = @classId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + cmd.Parameters.AddWithValue("@classId", player.charaWork.parameterSave.state_mainSkill[0]); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int index = reader.GetUInt16(0); + player.charaWork.command[index+32] = reader.GetUInt32(1); + player.charaWork.parameterSave.commandSlot_recastTime[index] = reader.GetUInt32(2); + } + } + + //Load Scenario Quests + query = @" + SELECT + slot, + questId + FROM characters_quest_scenario WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int index = reader.GetUInt16(0); + player.playerWork.questScenario[index] = 0xA0F00000 | reader.GetUInt32(1); + } + } + + //Load Local Guildleves + query = @" + SELECT + slot, + questId, + abandoned, + completed + FROM characters_quest_guildleve_local WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int index = reader.GetUInt16(0); + player.playerWork.questGuildleve[index] = 0xA0F00000 | reader.GetUInt32(1); + } + } + + //Load Regional Guildleve Quests + query = @" + SELECT + slot, + guildleveId, + abandoned, + completed + FROM characters_quest_guildleve_regional WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int index = reader.GetUInt16(0); + player.work.guildleveId[index] = reader.GetUInt16(1); + player.work.guildleveDone[index] = reader.GetBoolean(2); + player.work.guildleveChecked[index] = reader.GetBoolean(3); + } + } + + //Load NPC Linkshell + query = @" + SELECT + npcLinkshellId, + isCalling, + isExtra + FROM characters_npclinkshell WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int npcLSId = reader.GetUInt16(0); + player.playerWork.npcLinkshellChatCalling[npcLSId] = reader.GetBoolean(1); + player.playerWork.npcLinkshellChatExtra[npcLSId] = reader.GetBoolean(2); + } + } + + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + } + + public static SubPacket getLatestAchievements(Player player) + { + uint[] latestAchievements = new uint[5]; + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load Last 5 Completed + string query = @" + SELECT + characters_achievements.achievementId FROM characters_achievements + INNER JOIN gamedata_achievements ON characters_achievements.achievementId = gamedata_achievements.achievementId + WHERE characterId = @charId AND rewardPoints <> 0 ORDER BY timeDone LIMIT 5"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + int count = 0; + while (reader.Read()) + { + uint id = reader.GetUInt32(0); + latestAchievements[count++] = id; + } + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + + return SetLatestAchievementsPacket.buildPacket(player.actorId, latestAchievements); + } + + public static SubPacket getAchievementsPacket(Player player) + { + SetCompletedAchievementsPacket cheevosPacket = new SetCompletedAchievementsPacket(); + + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + string query = @" + SELECT packetOffsetId + FROM characters_achievements + INNER JOIN gamedata_achievements ON characters_achievements.achievementId = gamedata_achievements.achievementId + WHERE characterId = @charId AND timeDone IS NOT NULL"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + uint offset = reader.GetUInt32(0); + + if (offset < 0 || offset >= cheevosPacket.achievementFlags.Length) + { + Log.error("SQL Error; achievement flag offset id out of range: " + offset); + continue; + } + cheevosPacket.achievementFlags[offset] = true; + } + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + + return cheevosPacket.buildPacket(player.actorId); + } + + public static void loadZones(Efficient32bitHashTable zoneList) + { + int count = 0; + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + string query = @" + SELECT + id, + regionId, + zoneName, + dayMusic, + nightMusic, + battleMusic, + isInn, + canRideChocobo, + canStealth, + isInstanceRaid + FROM server_zones + WHERE zoneName IS NOT NULL"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) { + Zone zone = new Zone(reader.GetUInt32(0), reader.GetString(2), reader.GetUInt16(1), reader.GetUInt16(3), reader.GetUInt16(4), reader.GetUInt16(5), reader.GetBoolean(6), reader.GetBoolean(7), reader.GetBoolean(8), reader.GetBoolean(9)); + zoneList.Add(zone.actorId, zone); + count++; + } + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + + Log.info(String.Format("Loaded {0} zones.", count)); + } + } } diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 8e79f2d4..42f3674e 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -64,11 +64,18 @@ + + + + + + + @@ -84,17 +91,10 @@ - - - - - - - - + @@ -209,16 +209,16 @@ - + + + + - - - - + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 86723aa8..f622e2e4 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -33,6 +33,10 @@ using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.dataobjects.actors; using FFXIVClassic_Map_Server.dataobjects.chara.npc; using FFXIVClassic_Map_Server.actors; +using System.Net; +using FFXIVClassic_Map_Server.actors.debug; +using FFXIVClassic_Map_Server.actors.world; +using FFXIVClassic_Map_Server.common.EfficientHashTables; namespace FFXIVClassic_Lobby_Server { @@ -43,13 +47,18 @@ namespace FFXIVClassic_Lobby_Server List mConnections; StaticActors mStaticActors = new StaticActors(); - Zone inn = new Zone(); + + DebugProg debug = new DebugProg(); + WorldMaster worldMaster = new WorldMaster(); + + Efficient32bitHashTable zoneList = new Efficient32bitHashTable(); public PacketProcessor(Dictionary playerList, List connectionList) { mPlayers = playerList; mConnections = connectionList; - initNpcs(); + + Database.loadZones(zoneList); } public void processPacket(ClientConnection client, BasePacket packet) @@ -123,11 +132,7 @@ namespace FFXIVClassic_Lobby_Server if (actorID == 0) break; - - //Second connection - if (mPlayers.ContainsKey(actorID)) - player = mPlayers[actorID]; - + using (MemoryStream mem = new MemoryStream(reply2.data)) { using (BinaryWriter binReader = new BinaryWriter(mem)) @@ -137,7 +142,7 @@ namespace FFXIVClassic_Lobby_Server } } - if (player == null) + if (((IPEndPoint)client.socket.LocalEndPoint).Port == 54992) { player = new ConnectedPlayer(actorID); mPlayers[actorID] = player; @@ -184,30 +189,21 @@ namespace FFXIVClassic_Lobby_Server client.queuePacket(BasePacket.createPacket(PongPacket.buildPacket(player.actorID, pingPacket.time), true, false)); break; //Unknown - case 0x0002: - BasePacket packet196 = new BasePacket("./packets/196"); + case 0x0002: - BasePacket reply7 = new BasePacket("./packets/login/login7_data.bin"); - BasePacket reply8 = new BasePacket("./packets/login/login8_data.bin"); - BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); - BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); - BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); - BasePacket reply12 = new BasePacket("./packets/login/login12.bin"); + player.getActor().zone = zoneList.Get(player.getActor().zoneId); - // BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); - // BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); + BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); //Bed, Book created + BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); //Item Storage, Inn Door created + BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); //NPC Create ??? Final init #region replaceid //currancy.replaceActorID(player.actorID); //keyitems.replaceActorID(player.actorID); - - packet196.replaceActorID(player.actorID); - reply7.replaceActorID(player.actorID); - reply8.replaceActorID(player.actorID); + reply9.replaceActorID(player.actorID); reply10.replaceActorID(player.actorID); reply11.replaceActorID(player.actorID); - reply12.replaceActorID(player.actorID); #endregion client.queuePacket(SetMapPacket.buildPacket(player.actorID, 0xD1, 0xF4), true, false); @@ -217,7 +213,7 @@ namespace FFXIVClassic_Lobby_Server client.queuePacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false); client.queuePacket(SetWeatherPacket.buildPacket(player.actorID, SetWeatherPacket.WEATHER_CLEAR), true, false); - BasePacket actorPacket = player.getActor().getInitPackets(player.actorID); + BasePacket actorPacket = player.getActor().getSpawnPackets(player.actorID); client.queuePacket(actorPacket); //Retainers @@ -236,10 +232,10 @@ namespace FFXIVClassic_Lobby_Server BasePacket partyListPacket = BasePacket.createPacket(ListUtils.createPartyList(player.actorID, 0xF4, 1, 0x8000000000696df2, partyListEntries), true, false); client.queuePacket(partyListPacket); + #region itemsetup ////////ITEMS//////// client.queuePacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false); - #region itemsetup //TEST List items = new List(); @@ -276,14 +272,14 @@ namespace FFXIVClassic_Lobby_Server setinvPackets.Add(beginInventory); setinvPackets.Add(setInventory); setinvPackets.Add(endInventory); - #endregion - - client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); //client.queuePacket(currancy); //client.queuePacket(keyitems); + #endregion + #region equipsetup + client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); EquipmentSetupPacket initialEqupmentPacket = new EquipmentSetupPacket(); initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_BODY, 5); initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_HEAD, 3); @@ -291,7 +287,6 @@ namespace FFXIVClassic_Lobby_Server initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERGARMENT, 7); initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_MAINHAND, 2); initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_LEGS, 8); - #endregion //Equip Init client.queuePacket(InventorySetBeginPacket.buildPacket(player.actorID, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false); @@ -299,59 +294,28 @@ namespace FFXIVClassic_Lobby_Server client.queuePacket(InventorySetEndPacket.buildPacket(player.actorID), true, false); client.queuePacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false); - ////////ITEMS//////// + ////////ITEMS//////// - client.queuePacket(SetGrandCompanyPacket.buildPacket(player.actorID, player.actorID, 0x01, 0x1B, 0x1B, 0x1B), true, false); - client.queuePacket(SetPlayerTitlePacket.buildPacket(player.actorID, player.actorID, 0x00), true, false); - client.queuePacket(SetCurrentJobPacket.buildPacket(player.actorID, player.actorID, 0x13), true, false); - //client.queuePacket(packet196);//client.queuePacket(_0x196Packet.buildPacket(player.actorID, player.actorID), true, false); - client.queuePacket(SetChocoboNamePacket.buildPacket(player.actorID, player.actorID, "Boco"), true, false); - client.queuePacket(SetHasChocoboPacket.buildPacket(player.actorID, true), true, false); - client.queuePacket(SetHasGoobbuePacket.buildPacket(player.actorID, true), true, false); + #endregion - SetCompletedAchievementsPacket cheevos = new SetCompletedAchievementsPacket(); - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_BATTLE] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_CHARACTER] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_CURRENCY] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_DUNGEONS] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_EXPLORATION] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_GATHERING] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_GRAND_COMPANY] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_ITEMS] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_MATERIA] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_QUESTS] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_SEASONAL_EVENTS] = true; - cheevos.achievementFlags[SetCompletedAchievementsPacket.CATEGORY_SYNTHESIS] = true; - client.queuePacket(cheevos.buildPacket(player.actorID), true, false); + BasePacket tpacket = player.getActor().getInitPackets(player.actorID); + //tpacket.debugPrintPacket(); + client.queuePacket(tpacket); - client.queuePacket(SetLatestAchievementsPacket.buildPacket(player.actorID, new uint[5]), true, false); - client.queuePacket(SetAchievementPointsPacket.buildPacket(player.actorID, 0x00), true, false); + player.getActor().zone.addActorToZone(player.getActor()); - SetCutsceneBookPacket book = new SetCutsceneBookPacket(); - for (int i = 0; i < book.cutsceneFlags.Length; i++) - book.cutsceneFlags[i] = true; - client.queuePacket(book.buildPacket(player.actorID), true, false); + BasePacket innSpawn = player.getActor().zone.getSpawnPackets(player.actorID); + BasePacket debugSpawn = debug.getSpawnPackets(player.actorID); + BasePacket worldMasterSpawn = worldMaster.getSpawnPackets(player.actorID); + innSpawn.debugPrintPacket(); - //client.queuePacket(SetPlayerDreamPacket.buildPacket(player.actorID, 11), true, false); - - //BasePacket packet1a5 = new BasePacket("./packets/1ax/1a5"); - //packet1a5.replaceActorID(player.actorID); - //client.queuePacket(packet1a5); - + client.queuePacket(innSpawn); + client.queuePacket(debugSpawn); + client.queuePacket(worldMasterSpawn); - //loadTest(client, player); - //return; - inn.addActorToZone(player.getActor()); - // BasePacket tpacket = BasePacket.createPacket(player.getActor().createInitSubpackets(player.actorID), true, false); - // client.queuePacket(tpacket); - - client.queuePacket(reply7); - client.queuePacket(reply8); client.queuePacket(reply9); client.queuePacket(reply10); - // client.queuePacket(reply11); - client.queuePacket(reply12); - + client.queuePacket(reply11); break; //Chat Received @@ -368,9 +332,9 @@ namespace FFXIVClassic_Lobby_Server //Update Position UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); - + //Update Instance - List instanceUpdatePackets = player.updateInstance(inn.getActorsAroundActor(player.getActor(), 50)); + List instanceUpdatePackets = player.updateInstance(player.getActor().zone.getActorsAroundActor(player.getActor(), 50)); foreach (BasePacket bp in instanceUpdatePackets) client.queuePacket(bp); @@ -559,10 +523,12 @@ namespace FFXIVClassic_Lobby_Server */ private void initNpcs() { + /* List npcList = Database.getNpcList(); foreach (Npc npc in npcList) inn.addActorToZone(npc); Log.info(String.Format("Loaded {0} npcs...", npcList.Count)); + * */ } private void loadTest(ClientConnection client, ConnectedPlayer player) @@ -601,8 +567,8 @@ namespace FFXIVClassic_Lobby_Server packet.replaceActorID(entry.Value.actorID); actorPacket.replaceActorID(entry.Value.actorID); - entry.Value.getConnection2().queuePacket(packet); - entry.Value.getConnection2().queuePacket(actorPacket); + entry.Value.getConnection1().queuePacket(packet); + entry.Value.getConnection1().queuePacket(actorPacket); } diff --git a/FFXIVClassic Map Server/Program.cs b/FFXIVClassic Map Server/Program.cs index eb936fb9..4999ba82 100644 --- a/FFXIVClassic Map Server/Program.cs +++ b/FFXIVClassic Map Server/Program.cs @@ -6,8 +6,8 @@ using FFXIVClassic_Lobby_Server.common; using System.Runtime.InteropServices; using MySql.Data.MySqlClient; using System.Reflection; -using FFXIVClassic_Lobby_Server.dataobjects; using System.IO; +using FFXIVClassic_Lobby_Server.dataobjects; namespace FFXIVClassic_Lobby_Server { @@ -16,7 +16,6 @@ namespace FFXIVClassic_Lobby_Server static void Main(string[] args) { - #if DEBUG TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out); Debug.Listeners.Add(myWriter); diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index 59da20eb..59add233 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -226,13 +226,16 @@ namespace FFXIVClassic_Lobby_Server public void testCodePacket(uint id, uint value, string target) { - SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(); - changeProperty.addInt(id, value); + SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(target); + changeProperty.setTarget(target); + changeProperty.addInt(id, value); + changeProperty.addTarget(); foreach (KeyValuePair entry in mConnectedPlayerList) { SubPacket changePropertyPacket = changeProperty.buildPacket((entry.Value.actorID), (entry.Value.actorID)); + BasePacket packet = BasePacket.createPacket(changePropertyPacket, true, false); packet.debugPrintPacket(); if (entry.Value.getConnection1() != null) @@ -250,7 +253,7 @@ namespace FFXIVClassic_Lobby_Server { foreach (KeyValuePair entry in mConnectedPlayerList) { - SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(); + SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(target); changeProperty.addProperty(entry.Value.getActor(), name); changeProperty.addProperty(entry.Value.getActor(), "charaWork.parameterSave.hpMax[0]"); changeProperty.setTarget(target); diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index fbae8dc1..96257569 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -1,11 +1,9 @@ using FFXIVClassic_Lobby_Server; using FFXIVClassic_Lobby_Server.common; -using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic_Lobby_Server.packets; using FFXIVClassic_Map_Server.dataobjects.chara; using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.packets.send.actor; -using FFXIVClassic_Map_Server.packets.send.Actor; using System; using System.Collections; using System.Collections.Generic; @@ -24,14 +22,14 @@ namespace FFXIVClassic_Map_Server.dataobjects public uint displayNameId = 0xFFFFFFFF; public string customDisplayName; - public uint currentMainState = SetActorStatePacket.MAIN_STATE_PASSIVE; - public uint currentSubState = SetActorStatePacket.SUB_STATE_NONE; - public float positionX = SetActorPositionPacket.INNPOS_X, positionY = SetActorPositionPacket.INNPOS_Y, positionZ = SetActorPositionPacket.INNPOS_Z, rotation = SetActorPositionPacket.INNPOS_ROT; + public ushort currentMainState = SetActorStatePacket.MAIN_STATE_PASSIVE; + public ushort currentSubState = SetActorStatePacket.SUB_STATE_NONE; + public float positionX, positionY, positionZ, rotation; public float oldPositionX, oldPositionY, oldPositionZ, oldRotation; public ushort moveState, oldMoveState; - public uint currentZoneId; - + public uint zoneId; + public Zone zone = null; public bool isZoning = false; public bool spawnedFirstTime = false; @@ -102,7 +100,7 @@ namespace FFXIVClassic_Map_Server.dataobjects return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, classParams); } - public virtual BasePacket getInitPackets(uint playerActorId) + public virtual BasePacket getSpawnPackets(uint playerActorId) { List subpackets = new List(); subpackets.Add(createAddActorPacket(playerActorId)); @@ -114,7 +112,14 @@ namespace FFXIVClassic_Map_Server.dataobjects subpackets.Add(createScriptBindPacket(playerActorId)); return BasePacket.createPacket(subpackets, true, false); } - + + public virtual BasePacket getInitPackets(uint playerActorId) + { + SetActorPropetyPacket initProperties = new SetActorPropetyPacket("/_init"); + initProperties.addTarget(); + return BasePacket.createPacket(initProperties.buildPacket(playerActorId, actorId), true, false); + } + public override bool Equals(Object obj) { Actor actorObj = obj as Actor; diff --git a/FFXIVClassic Map Server/Zone.cs b/FFXIVClassic Map Server/actors/area/Zone.cs similarity index 71% rename from FFXIVClassic Map Server/Zone.cs rename to FFXIVClassic Map Server/actors/area/Zone.cs index b305e400..5dcfea5d 100644 --- a/FFXIVClassic Map Server/Zone.cs +++ b/FFXIVClassic Map Server/actors/area/Zone.cs @@ -1,5 +1,8 @@ using FFXIVClassic_Lobby_Server.common; +using FFXIVClassic_Lobby_Server.packets; using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.packets.send.actor; using System; using System.Collections.Generic; using System.Linq; @@ -8,19 +11,41 @@ using System.Threading.Tasks; namespace FFXIVClassic_Map_Server { - class Zone + class Zone : Actor { - public uint mapId; + public string zoneName; + public ushort regionId; + public bool canStealth, isInn, canRideChocobo, isInstanceRaid; public ushort weatherNormal, weatherCommon, weatherRare; public ushort bgmDay, bgmNight, bgmBattle; + public int boundingGridSize = 50; public int minX = -100, minY = -100, maxX = 100, maxY = 100; private int numXBlocks, numYBlocks; private int halfWidth, halfHeight; private List[,] actorBlock; - public Zone() + public Zone(uint id, string zoneName, ushort regionId, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool canStealth, bool isInn, bool canRideChocobo, bool isInstanceRaid) + : base(id) { + + this.zoneName = zoneName; + this.regionId = regionId; + this.canStealth = canStealth; + this.isInn = isInn; + this.canRideChocobo = canRideChocobo; + this.isInstanceRaid = isInstanceRaid; + + this.bgmDay = bgmDay; + this.bgmNight = bgmNight; + this.bgmBattle = bgmBattle; + + this.displayNameId = 0; + this.customDisplayName = "_areaMaster"; + this.actorName = String.Format("_areaMaster@{0:X5}",id<<8); + + this.className = "ZoneMasterPrvI0"; + numXBlocks = (maxX - minX) / boundingGridSize; numYBlocks = (maxY - minY) / boundingGridSize; actorBlock = new List[numXBlocks, numYBlocks]; @@ -37,6 +62,26 @@ namespace FFXIVClassic_Map_Server } + public override SubPacket createScriptBindPacket(uint playerActorId) + { + List lParams; + lParams = LuaUtils.createLuaParamList("/Area/Zone/ZoneMasterPrvI0", false, true, zoneName, "", 0xFFFFFFFF, false, false, canStealth, isInn, false, false, false, false, false, false); + return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams); + } + + public override BasePacket getSpawnPackets(uint playerActorId) + { + List subpackets = new List(); + subpackets.Add(createAddActorPacket(playerActorId)); + subpackets.Add(createSpeedPacket(playerActorId)); + subpackets.Add(createSpawnPositonPacket(playerActorId, 0x1)); + subpackets.Add(createNamePacket(playerActorId)); + subpackets.Add(createStatePacket(playerActorId)); + subpackets.Add(createIsZoneingPacket(playerActorId)); + subpackets.Add(createScriptBindPacket(playerActorId)); + return BasePacket.createPacket(subpackets, true, false); + } + #region Actor Management public void addActorToZone(Actor actor) diff --git a/FFXIVClassic Map Server/actors/chara/AetheryteWork.cs b/FFXIVClassic Map Server/actors/chara/AetheryteWork.cs new file mode 100644 index 00000000..fd1f33b9 --- /dev/null +++ b/FFXIVClassic Map Server/actors/chara/AetheryteWork.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.dataobjects.chara +{ + class AetheryteWork + { + public int iconGil; + public short guildleveId; + public short clearTime; + public int missionBonus; + public int difficultyBonus; + + public byte factionNumber; + public int factionBonus; + public byte factionCredit; + + public int glRewardItem; + public int glRewardNumber; + public int glRewardSubItem; + public int glRewardSubNumber; + + public byte difficulty; + } +} diff --git a/FFXIVClassic Map Server/actors/chara/BattleSave.cs b/FFXIVClassic Map Server/actors/chara/BattleSave.cs index 4d36202e..da2c38ac 100644 --- a/FFXIVClassic Map Server/actors/chara/BattleSave.cs +++ b/FFXIVClassic Map Server/actors/chara/BattleSave.cs @@ -8,11 +8,12 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara { class BattleSave { - public float potencial; - public int skillLevel; - public int skillLevelCap; - public int[] skillPoint; + public float potencial = 6.6f; + public short[] skillLevel = new short[52]; + public short[] skillLevelCap = new short[52]; + public short[] skillPoint = new short[52]; + public short physicalLevel; public int physicalExp; public bool[] negotiationFlag= new bool[2]; diff --git a/FFXIVClassic Map Server/actors/chara/BattleTemp.cs b/FFXIVClassic Map Server/actors/chara/BattleTemp.cs index 78ecab38..2c90f8f5 100644 --- a/FFXIVClassic Map Server/actors/chara/BattleTemp.cs +++ b/FFXIVClassic Map Server/actors/chara/BattleTemp.cs @@ -8,27 +8,29 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara { class BattleTemp { - public const uint NAMEPLATE_SHOWN = 0xFBFBCFB1; - public const uint TARGETABLE = 0x2138FD71; + public const uint NAMEPLATE_SHOWN = 0; + public const uint TARGETABLE = 1; + //public const uint NAMEPLATE_SHOWN2 = 2; + public const uint NAMEPLATE_SHOWN2 = 3; - public const uint STAT_STRENGTH = 4; - public const uint STAT_VITALITY = 5; - public const uint STAT_DEXTERITY = 6; - public const uint STAT_INTELLIGENCE = 7; - public const uint STAT_MIND = 8; - public const uint STAT_PIETY = 9; + public const uint STAT_STRENGTH = 3; + public const uint STAT_VITALITY = 4; + public const uint STAT_DEXTERITY = 5; + public const uint STAT_INTELLIGENCE = 6; + public const uint STAT_MIND = 7; + public const uint STAT_PIETY = 8; - public const uint STAT_RESISTANCE_FIRE = 10; - public const uint STAT_RESISTANCE_ICE = 11; - public const uint STAT_RESISTANCE_WIND = 12; - public const uint STAT_RESISTANCE_LIGHTNING = 3; - public const uint STAT_RESISTANCE_EARTH = 14; - public const uint STAT_RESISTANCE_WATER = 15; + public const uint STAT_RESISTANCE_FIRE = 9; + public const uint STAT_RESISTANCE_ICE = 10; + public const uint STAT_RESISTANCE_WIND = 11; + public const uint STAT_RESISTANCE_LIGHTNING = 12; + public const uint STAT_RESISTANCE_EARTH = 13; + public const uint STAT_RESISTANCE_WATER = 14; - public const uint STAT_ATTACK = 18; - public const uint STAT_ACCURACY = 16; - public const uint STAT_NORMALDEFENSE = 19; - public const uint STAT_EVASION = 17; + public const uint STAT_ATTACK = 17; + public const uint STAT_ACCURACY = 15; + public const uint STAT_NORMALDEFENSE = 18; + public const uint STAT_EVASION = 16; public const uint STAT_ATTACK_MAGIC = 24; public const uint STAT_HEAL_MAGIC = 25; public const uint STAT_ENCHANCEMENT_MAGIC_POTENCY = 26; @@ -45,8 +47,8 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara public const uint STAT_HARVEST_LIMIT = 34; public const uint STAT_HARVEST_RATE = 35; - public int[] castGauge_speed = new int[2]; + public float[] castGauge_speed = { 1.0f, 0.25f}; public bool[] timingCommandFlag = new bool[4]; - public ushort[] generalParameter = new ushort[32]; + public ushort[] generalParameter = new ushort[35]; } } diff --git a/FFXIVClassic Map Server/actors/chara/CharaWork.cs b/FFXIVClassic Map Server/actors/chara/CharaWork.cs index adb50eed..49b999aa 100644 --- a/FFXIVClassic Map Server/actors/chara/CharaWork.cs +++ b/FFXIVClassic Map Server/actors/chara/CharaWork.cs @@ -18,17 +18,21 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara public EventSave eventSave = new EventSave(); public EventTemp eventTemp = new EventTemp(); + public bool gameParameter = false; + + public byte[] property = new byte[32]; public ushort[] status = new ushort[20]; public uint[] statusShownTime = new uint[20]; - public int[] command = new int[64]; - public int[] commandCategory = new int[64]; - public int commandBorder = 0x20; - public bool commandAcquired = false; - public bool[] additionalCommandAcquired = new bool[1]; + public uint[] command = new uint[64]; //ACTORS + public byte[] commandCategory = new byte[64]; + public byte commandBorder = 0x20; + public bool[] commandAcquired = new bool[4096]; + public bool[] additionalCommandAcquired = new bool[36]; + public uint currentContentGroup; public uint depictionJudge = 0xa0f50911; } } diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index 29cd0d38..0a7c08eb 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -1,4 +1,5 @@ using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.actors.chara; using FFXIVClassic_Map_Server.packets.send.actor; using System; using System.Collections.Generic; @@ -45,12 +46,15 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara public uint currentLockedTarget = 0xC0000000; public uint currentActorIcon = 0; - - public CharaWork charaWork = new CharaWork(); - public PlayerWork playerWork = new PlayerWork(); - public Character(uint actorId) : base(actorId) - { + public Work work = new Work(); + public CharaWork charaWork = new CharaWork(); + + public Character(uint actorID) : base(actorID) + { + //Init timer array to "notimer" + for (int i = 0; i < charaWork.statusShownTime.Length; i++) + charaWork.statusShownTime[i] = 0xFFFFFFFF; } public SubPacket createAppearancePacket(uint playerActorId) diff --git a/FFXIVClassic Map Server/actors/chara/EventSave.cs b/FFXIVClassic Map Server/actors/chara/EventSave.cs index 3f289413..7365aa11 100644 --- a/FFXIVClassic Map Server/actors/chara/EventSave.cs +++ b/FFXIVClassic Map Server/actors/chara/EventSave.cs @@ -9,7 +9,7 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara class EventSave { public bool bazaar; - public float bazaarTax; - public int repairType; + public byte bazaarTax; + public byte repairType; } } diff --git a/FFXIVClassic Map Server/actors/chara/ParameterSave.cs b/FFXIVClassic Map Server/actors/chara/ParameterSave.cs index eb0e614b..1a4dab00 100644 --- a/FFXIVClassic Map Server/actors/chara/ParameterSave.cs +++ b/FFXIVClassic Map Server/actors/chara/ParameterSave.cs @@ -8,19 +8,30 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara { class ParameterSave { - public int[] hp = new int[1]; - public int[] hpMax = new int[1]; - public int mp; - public int mpMax; + public short[] hp = new short[8]; + public short[] hpMax = new short[8]; + public short mp; + public short mpMax; - public int[] state_mainSkill = new int[4]; - public int state_mainSkillLevel; + public byte[] state_mainSkill = new byte[4]; + public ushort state_mainSkillLevel; - public int[] state_boostPointForSkill; + public byte[] state_boostPointForSkill = new byte[4]; + + public uint[] commandSlot_recastTime = new uint[40]; + public bool[] commandSlot_compatibility = new bool[40]; - public int[] commandSlot_compatibility; - public int[] commandSlot_recastTime; + public ushort[] giftCommandSlot_commandId = new ushort[10]; - public int[] giftCommandSlot_commandId; + public ushort[] constanceCommandSlot_commandId = new ushort[10]; + + public byte abilityCostPoint_used; + public byte abilityCostPoint_max; + + public byte giftCostPoint_used; + public byte giftCostPoint_max; + + public byte constanceCostPoint_used; + public byte constanceCostPoint_max; } } diff --git a/FFXIVClassic Map Server/actors/chara/ParameterTemp.cs b/FFXIVClassic Map Server/actors/chara/ParameterTemp.cs index 9d77e566..d912aec8 100644 --- a/FFXIVClassic Map Server/actors/chara/ParameterTemp.cs +++ b/FFXIVClassic Map Server/actors/chara/ParameterTemp.cs @@ -8,16 +8,16 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara { class ParameterTemp { - public int tp = 0; + public short tp = 0; public int targetInformation = 0; - public int[] maxCommandRecastTime = new int[40]; + public ushort[] maxCommandRecastTime = new ushort[40]; - public float[] forceControl_float_forClientSelf = new float[4]; - public short[] forceControl_int16_forClientSelf = new short[2]; + public float[] forceControl_float_forClientSelf = { 1.0f, 1.0f, 0.0f, 0.0f}; + public short[] forceControl_int16_forClientSelf = { -1, -1 }; - public int[] otherClassAbilityCount = new int[2]; - public int[] giftCount = new int[2]; + public byte[] otherClassAbilityCount = new byte[2]; + public byte[] giftCount = new byte[2]; } } diff --git a/FFXIVClassic Map Server/actors/chara/Work.cs b/FFXIVClassic Map Server/actors/chara/Work.cs new file mode 100644 index 00000000..4dd577b5 --- /dev/null +++ b/FFXIVClassic Map Server/actors/chara/Work.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.actors.chara +{ + class Work + { + public ushort[] guildleveId = new ushort[16]; + public bool[] guildleveDone = new bool[16]; + public bool[] guildleveChecked = new bool[16]; + + public bool betacheck = false; + + public bool[] event_achieve_aetheryte = new bool[512]; + } +} diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index b91815b8..a4ca84d7 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -1,6 +1,5 @@ using FFXIVClassic_Lobby_Server; using FFXIVClassic_Lobby_Server.common; -using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic_Lobby_Server.packets; using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.packets.send.actor; @@ -30,35 +29,6 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara.npc if (initParams.Length != 0) this.classParams = LuaUtils.readLuaParams(initParams); - setPlayerAppearance(); - } - - public void setPlayerAppearance() - { - DBAppearance appearance = Database.getAppearance(false, actorId); - - if (appearance == null) - return; - - modelId = DBAppearance.getTribeModel(appearance.tribe); - appearanceIds[SIZE] = appearance.size; - appearanceIds[COLORINFO] = (uint)(appearance.skinColor | (appearance.hairColor << 10) | (appearance.eyeColor << 20)); - appearanceIds[FACEINFO] = PrimitiveConversion.ToUInt32(appearance.getFaceInfo()); - appearanceIds[HIGHLIGHT_HAIR] = (uint)(appearance.hairHighlightColor | appearance.hairStyle << 10); - appearanceIds[VOICE] = appearance.voice; - appearanceIds[WEAPON1] = appearance.mainHand; - appearanceIds[WEAPON2] = appearance.offHand; - appearanceIds[HEADGEAR] = appearance.head; - appearanceIds[BODYGEAR] = appearance.body; - appearanceIds[LEGSGEAR] = appearance.legs; - appearanceIds[HANDSGEAR] = appearance.hands; - appearanceIds[FEETGEAR] = appearance.feet; - appearanceIds[WAISTGEAR] = appearance.waist; - appearanceIds[R_EAR] = appearance.rightEar; - appearanceIds[L_EAR] = appearance.leftEar; - appearanceIds[R_FINGER] = appearance.rightFinger; - appearanceIds[L_FINGER] = appearance.leftFinger; - } public override BasePacket getInitPackets(uint playerActorId) diff --git a/FFXIVClassic Map Server/actors/chara/npc/NpcWork.cs b/FFXIVClassic Map Server/actors/chara/npc/NpcWork.cs new file mode 100644 index 00000000..c10b7047 --- /dev/null +++ b/FFXIVClassic Map Server/actors/chara/npc/NpcWork.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.dataobjects.chara +{ + class NpcWork + { + public short pushCommand; + public int pushCommandSub; + public byte pushCommandPriority; + public byte hateType; + } +} diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index fa649d50..b350a3fa 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -1,10 +1,11 @@ using FFXIVClassic_Lobby_Server; using FFXIVClassic_Lobby_Server.common; -using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic_Lobby_Server.packets; -using FFXIVClassic_Map_Server.dataobjects.database; using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.packets.send.actor; +using FFXIVClassic_Map_Server.packets.send.player; +using FFXIVClassic_Map_Server.utils; +using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Linq; @@ -39,7 +40,23 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara public uint[] timers = new uint[20]; - PlayerWork playerWork = new PlayerWork(); + public ushort currentJob; + + public uint currentTitle; + + public byte gcCurrent; + public byte gcRankLimsa; + public byte gcRankGridania; + public byte gcRankUldah; + + public bool hasChocobo; + public bool hasGoobbue; + public byte chocoboAppearance; + public string chocoboName; + + public uint achievementPoints; + + public PlayerWork playerWork = new PlayerWork(); public Player(uint actorID) : base(actorID) { @@ -47,58 +64,54 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara className = "Player"; currentSubState = SetActorStatePacket.SUB_STATE_PLAYER; - DBStats stats = Database.getCharacterStats(actorID); - charaWork.property[0] = 1; charaWork.property[1] = 1; charaWork.property[2] = 1; - charaWork.property[4] = 1; + charaWork.property[4] = 1; - charaWork.parameterSave.hp[0] = stats.hp; - charaWork.parameterSave.hpMax[0] = stats.hpMax; - charaWork.parameterSave.mp = stats.mp; - charaWork.parameterSave.mpMax = stats.mpMax; + charaWork.command[0] = 0xA0F00000 | 21001; + charaWork.command[1] = 0xA0F00000 | 21002; + charaWork.command[2] = 0xA0F00000 | 12003; + charaWork.command[3] = 0xA0F00000 | 12004; + charaWork.command[4] = 0xA0F00000 | 21005; + charaWork.command[5] = 0xA0F00000 | 21006; + charaWork.command[6] = 0xA0F00000 | 21007; + charaWork.command[7] = 0xA0F00000 | 12009; + charaWork.command[8] = 0xA0F00000 | 12010; + charaWork.command[9] = 0xA0F00000 | 12005; + charaWork.command[10] = 0xA0F00000 | 12007; + charaWork.command[11] = 0xA0F00000 | 12011; + charaWork.command[12] = 0xA0F00000 | 22012; + charaWork.command[13] = 0xA0F00000 | 22013; + charaWork.command[14] = 0xA0F00000 | 29497; + charaWork.command[15] = 0xA0F00000 | 22015; - charaWork.parameterSave.state_mainSkill[0] = 3; - charaWork.parameterSave.state_mainSkillLevel = 1; + charaWork.command[32] = 0xA0F00000 | 27155; + //charaWork.command[33] = 0xA0F00000 | 27150; + charaWork.command[34] = 0xA0F00000 | 27300; - charaWork.battleSave.skillLevel = 1; - charaWork.battleSave.skillLevelCap = 2; - charaWork.battleSave.potencial = 0.5f; - charaWork.battleSave.physicalExp = 1; - charaWork.battleSave.negotiationFlag[0] = false; - charaWork.battleSave.negotiationFlag[1] = false; + charaWork.commandAcquired[27150 - 26000] = true; - for (int i = 0; i < 20; i++) - charaWork.statusShownTime[i] = 0xFFFFFFFF; + playerWork.questScenarioComplete[110001 - 110001] = true; + playerWork.questGuildleveComplete[120050 - 120001] = true; + + for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++ ) + charaWork.additionalCommandAcquired[i] = true; - setPlayerAppearance(); + for (int i = 0; i < charaWork.commandCategory.Length; i++) + charaWork.commandCategory[i] = 1; + + charaWork.battleTemp.generalParameter[3] = 1; + + + charaWork.eventSave.bazaarTax = 5; + charaWork.battleSave.potencial = 6.6f; + + charaWork.commandBorder = 0x20; + + Database.loadPlayerCharacter(this); } - - public void setPlayerAppearance() - { - DBAppearance appearance = Database.getAppearance(true, actorId); - - modelId = DBAppearance.getTribeModel(appearance.tribe); - appearanceIds[SIZE] = appearance.size; - appearanceIds[COLORINFO] = (uint)(appearance.skinColor | (appearance.hairColor << 10) | (appearance.eyeColor << 20)); - appearanceIds[FACEINFO] = PrimitiveConversion.ToUInt32(appearance.getFaceInfo()); - appearanceIds[HIGHLIGHT_HAIR] = (uint)(appearance.hairHighlightColor | appearance.hairStyle << 10); - appearanceIds[VOICE] = appearance.voice; - appearanceIds[WEAPON1] = appearance.mainHand; - appearanceIds[WEAPON2] = appearance.offHand; - appearanceIds[HEADGEAR] = appearance.head; - appearanceIds[BODYGEAR] = appearance.body; - appearanceIds[LEGSGEAR] = appearance.legs; - appearanceIds[HANDSGEAR] = appearance.hands; - appearanceIds[FEETGEAR] = appearance.feet; - appearanceIds[WAISTGEAR] = appearance.waist; - appearanceIds[R_EAR] = appearance.rightEar; - appearanceIds[L_EAR] = appearance.leftEar; - appearanceIds[R_FINGER] = appearance.rightFinger; - appearanceIds[L_FINGER] = appearance.leftFinger; - } - + public List create0x132Packets(uint playerActorId) { List packets = new List(); @@ -125,7 +138,7 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams); } - public override BasePacket getInitPackets(uint playerActorId) + public override BasePacket getSpawnPackets(uint playerActorId) { List subpackets = new List(); subpackets.Add(createAddActorPacket(playerActorId)); @@ -141,14 +154,214 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara subpackets.Add(createInitStatusPacket(playerActorId)); subpackets.Add(createSetActorIconPacket(playerActorId)); subpackets.Add(createIsZoneingPacket(playerActorId)); - subpackets.Add(createScriptBindPacket(playerActorId)); - + subpackets.AddRange(createPlayerRelatedPackets(playerActorId)); + subpackets.Add(createScriptBindPacket(playerActorId)); return BasePacket.createPacket(subpackets, true, false); } + public List createPlayerRelatedPackets(uint playerActorId) + { + List subpackets = new List(); + + if (gcCurrent != 0) + subpackets.Add(SetGrandCompanyPacket.buildPacket(actorId, playerActorId, gcCurrent, gcRankLimsa, gcRankGridania, gcRankUldah)); + + if (currentTitle != 0) + subpackets.Add(SetPlayerTitlePacket.buildPacket(actorId, playerActorId, currentTitle)); + + if (currentJob != 0) + subpackets.Add(SetCurrentJobPacket.buildPacket(actorId, playerActorId, currentJob)); + + if (isMyPlayer(playerActorId)) + { + subpackets.Add(_0x196Packet.buildPacket(playerActorId, playerActorId)); + + if (hasChocobo && chocoboName != null && !chocoboName.Equals("")) + { + subpackets.Add(SetChocoboNamePacket.buildPacket(actorId, playerActorId, chocoboName)); + subpackets.Add(SetHasChocoboPacket.buildPacket(playerActorId, hasChocobo)); + } + + if (hasGoobbue) + subpackets.Add(SetHasGoobbuePacket.buildPacket(playerActorId, hasGoobbue)); + + subpackets.Add(SetAchievementPointsPacket.buildPacket(playerActorId, achievementPoints)); + subpackets.Add(Database.getLatestAchievements(this)); + subpackets.Add(Database.getAchievementsPacket(this)); + + /* + if (isInn) + { + SetCutsceneBookPacket book = new SetCutsceneBookPacket(); + for (int i = 0; i < book.cutsceneFlags.Length; i++) + book.cutsceneFlags[i] = true; + client.queuePacket(book.buildPacket(player.actorID), true, false); + + // + //subpackets.Add(SetPlayerDreamPacket.buildPacket(playerActorId, ); + } + */ + } + + return subpackets; + } + + public override BasePacket getInitPackets(uint playerActorId) + { + ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId); + + propPacketUtil.addProperty("charaWork.eventSave.bazaarTax"); + propPacketUtil.addProperty("charaWork.battleSave.potencial"); + + //Properties + for (int i = 0; i < charaWork.property.Length; i++) + { + if (charaWork.property[i] != 0) + propPacketUtil.addProperty(String.Format("charaWork.property[{0}]", i)); + } + + //Parameters + propPacketUtil.addProperty("charaWork.parameterSave.hp[0]"); + propPacketUtil.addProperty("charaWork.parameterSave.hpMax[0]"); + propPacketUtil.addProperty("charaWork.parameterSave.mp"); + propPacketUtil.addProperty("charaWork.parameterSave.mpMax"); + propPacketUtil.addProperty("charaWork.parameterTemp.tp"); + propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkill[0]"); + propPacketUtil.addProperty("charaWork.parameterSave.state_mainSkillLevel"); + + //Status Times + for (int i = 0; i < charaWork.statusShownTime.Length; i++) + { + if (charaWork.statusShownTime[i] != 0xFFFFFFFF) + propPacketUtil.addProperty(String.Format("charaWork.statusShownTime[{0}]", i)); + } + + //General Parameters + for (int i = 3; i < charaWork.battleTemp.generalParameter.Length; i++) + { + if (charaWork.battleTemp.generalParameter[i] != 0) + propPacketUtil.addProperty(String.Format("charaWork.battleTemp.generalParameter[{0}]", i)); + } + + propPacketUtil.addProperty("charaWork.battleTemp.castGauge_speed[0]"); + propPacketUtil.addProperty("charaWork.battleTemp.castGauge_speed[1]"); + + //Battle Save Skillpoint + + //Commands + propPacketUtil.addProperty("charaWork.commandBorder"); + + + for (int i = 0; i < charaWork.command.Length; i++) + { + if (charaWork.command[i] != 0) + propPacketUtil.addProperty(String.Format("charaWork.command[{0}]", i)); + } + + /* + for (int i = 0; i < charaWork.commandCategory.Length; i++) + { + charaWork.commandCategory[i] = 1; + if (charaWork.commandCategory[i] != 0) + propPacketUtil.addProperty(String.Format("charaWork.commandCategory[{0}]", i)); + } + + for (int i = 0; i < charaWork.commandAcquired.Length; i++) + { + if (charaWork.commandAcquired[i] != false) + propPacketUtil.addProperty(String.Format("charaWork.commandAcquired[{0}]", i)); + } + */ + + for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++) + { + if (charaWork.additionalCommandAcquired[i] != false) + propPacketUtil.addProperty(String.Format("charaWork.additionalCommandAcquired[{0}]", i)); + } + + for (int i = 0; i < charaWork.parameterSave.commandSlot_compatibility.Length; i++) + { + charaWork.parameterSave.commandSlot_compatibility[i] = true; + if (charaWork.parameterSave.commandSlot_compatibility[i]) + propPacketUtil.addProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", i)); + } + + /* + for (int i = 0; i < charaWork.parameterSave.commandSlot_recastTime.Length; i++) + { + if (charaWork.parameterSave.commandSlot_recastTime[i] != 0) + propPacketUtil.addProperty(String.Format("charaWork.parameterSave.commandSlot_recastTime[{0}]", i)); + } + */ + + //System + propPacketUtil.addProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[0]"); + propPacketUtil.addProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[1]"); + propPacketUtil.addProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[0]"); + propPacketUtil.addProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[1]"); + + charaWork.parameterTemp.otherClassAbilityCount[0] = 4; + charaWork.parameterTemp.otherClassAbilityCount[1] = 5; + charaWork.parameterTemp.giftCount[1] = 5; + + propPacketUtil.addProperty("charaWork.parameterTemp.otherClassAbilityCount[0]"); + propPacketUtil.addProperty("charaWork.parameterTemp.otherClassAbilityCount[1]"); + propPacketUtil.addProperty("charaWork.parameterTemp.giftCount[1]"); + + propPacketUtil.addProperty("charaWork.depictionJudge"); + + //Scenario + for (int i = 0; i < playerWork.questScenario.Length; i++) + { + if (playerWork.questScenario[i] != 0) + propPacketUtil.addProperty(String.Format("playerWork.questScenario[{0}]", i)); + } + + //Guildleve - Local + for (int i = 0; i < playerWork.questGuildleve.Length; i++) + { + if (playerWork.questGuildleve[i] != 0) + propPacketUtil.addProperty(String.Format("playerWork.questGuildleve[{0}]", i)); + } + + //Guildleve - Regional + for (int i = 0; i < work.guildleveId.Length; i++) + { + if (work.guildleveId[i] != 0) + propPacketUtil.addProperty(String.Format("work.guildleveId[{0}]", i)); + if (work.guildleveDone[i] != false) + propPacketUtil.addProperty(String.Format("work.guildleveDone[{0}]", i)); + if (work.guildleveChecked[i] != false) + propPacketUtil.addProperty(String.Format("work.guildleveChecked[{0}]", i)); + } + + //NPC Linkshell + for (int i = 0; i < playerWork.npcLinkshellChatCalling.Length; i++) + { + if (playerWork.npcLinkshellChatCalling[i] != false) + propPacketUtil.addProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", i)); + if (playerWork.npcLinkshellChatExtra[i] != false) + propPacketUtil.addProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", i)); + } + + propPacketUtil.addProperty("playerWork.restBonusExpRate"); + + //Profile + propPacketUtil.addProperty("playerWork.tribe"); + propPacketUtil.addProperty("playerWork.guardian"); + propPacketUtil.addProperty("playerWork.birthdayMonth"); + propPacketUtil.addProperty("playerWork.birthdayDay"); + propPacketUtil.addProperty("playerWork.initialTown"); + + return propPacketUtil.done(); + } + public bool isMyPlayer(uint otherActorId) { return actorId == otherActorId; - } + } + + + } } diff --git a/FFXIVClassic Map Server/actors/chara/player/PlayerWork.cs b/FFXIVClassic Map Server/actors/chara/player/PlayerWork.cs index 9d5cbcef..050ec57d 100644 --- a/FFXIVClassic Map Server/actors/chara/player/PlayerWork.cs +++ b/FFXIVClassic Map Server/actors/chara/player/PlayerWork.cs @@ -8,19 +8,19 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara { class PlayerWork { - public int tribe; - public int guardian; - public int birthdayMonth; - public int birthdayDay; - public int initialTown; + public byte tribe; + public byte guardian; + public byte birthdayMonth; + public byte birthdayDay; + public byte initialTown; - public int restBonusExpRate; + public float restBonusExpRate = 1.5f; - public int[] questScenario = new int[16]; - public int[] questGuildLeve = new int[8]; + public uint[] questScenario = new uint[16]; + public uint[] questGuildleve = new uint[8]; - public int questScenarioComplete; - public int questGuildleveComplete; + public bool[] questScenarioComplete = new bool[2048]; + public bool[] questGuildleveComplete = new bool[2048]; public bool isContentsCommand; @@ -28,24 +28,24 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara public int castEndClient; public int[] comboNextCommandId = new int[2]; - public int comboCostBonusRate; + public float comboCostBonusRate; public bool isRemainBonusPoint; - public int[] npcLinkshellChatCalling = new int[64]; - public int[] npcLinkshellChatExtra = new int[64]; + public bool[] npcLinkshellChatCalling = new bool[64]; + public bool[] npcLinkshellChatExtra = new bool[64]; public int variableCommandConfirmWarp; - public int variableCommandConfirmWarpSender; + public string variableCommandConfirmWarpSender; public int variableCommandConfirmWarpSenderByID; - public int variableCommandConfirmWarpSenderSex; + public byte variableCommandConfirmWarpSenderSex; public int variableCommandConfirmWarpPlace; public int variableCommandConfirmRaise; - public int variableCommandConfirmRaiseSender; + public string variableCommandConfirmRaiseSender; public int variableCommandConfirmRaiseSenderByID; - public int variableCommandConfirmRaiseSenderSex; + public byte variableCommandConfirmRaiseSenderSex; public int variableCommandConfirmRaisePlace; - + } } diff --git a/FFXIVClassic Map Server/actors/debug/Debug.cs b/FFXIVClassic Map Server/actors/debug/Debug.cs new file mode 100644 index 00000000..13192ff4 --- /dev/null +++ b/FFXIVClassic Map Server/actors/debug/Debug.cs @@ -0,0 +1,47 @@ +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.packets.send.actor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.actors.debug +{ + class DebugProg : Actor + { + + public DebugProg() + : base(0x5FF80002) + { + this.displayNameId = 0; + this.customDisplayName = "debug"; + + this.actorName = "debug"; + this.className = "Debug"; + } + + public override SubPacket createScriptBindPacket(uint playerActorId) + { + List lParams; + lParams = LuaUtils.createLuaParamList("/System/Debug.prog", false, false, false, false, true, 0xC51F, true, true); + return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams); + } + + public override BasePacket getSpawnPackets(uint playerActorId) + { + List subpackets = new List(); + subpackets.Add(createAddActorPacket(playerActorId)); + subpackets.Add(createSpeedPacket(playerActorId)); + subpackets.Add(createSpawnPositonPacket(playerActorId, 0x1)); + subpackets.Add(createNamePacket(playerActorId)); + subpackets.Add(createStatePacket(playerActorId)); + subpackets.Add(createIsZoneingPacket(playerActorId)); + subpackets.Add(createScriptBindPacket(playerActorId)); + return BasePacket.createPacket(subpackets, true, false); + } + + } +} diff --git a/FFXIVClassic Map Server/actors/director/WeatherDirector.cs b/FFXIVClassic Map Server/actors/director/WeatherDirector.cs new file mode 100644 index 00000000..d96e391c --- /dev/null +++ b/FFXIVClassic Map Server/actors/director/WeatherDirector.cs @@ -0,0 +1,49 @@ +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.packets.send.actor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.actors.director +{ + class WeatherDirector : Actor + { + private uint weatherId; + + public WeatherDirector(uint weatherId, Zone zone) + : base(0x5FF80002) + { + this.weatherId = weatherId; + + this.displayNameId = 0; + this.customDisplayName = String.Format("weatherDire_{0}", zone.zoneName, zone.actorId); + + this.actorName = String.Format("weatherDire_{0}@{0:04x}", zone.zoneName, zone.actorId); + this.className = "Debug"; + } + + public override SubPacket createScriptBindPacket(uint playerActorId) + { + List lParams; + lParams = LuaUtils.createLuaParamList("/Director/Weather/WeatherDirector", false, false, false, false, weatherId); + return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams); + } + + public override BasePacket getSpawnPackets(uint playerActorId) + { + List subpackets = new List(); + subpackets.Add(createAddActorPacket(playerActorId)); + subpackets.Add(createSpeedPacket(playerActorId)); + subpackets.Add(createSpawnPositonPacket(playerActorId, 0x1)); + subpackets.Add(createNamePacket(playerActorId)); + subpackets.Add(createStatePacket(playerActorId)); + subpackets.Add(createIsZoneingPacket(playerActorId)); + subpackets.Add(createScriptBindPacket(playerActorId)); + return BasePacket.createPacket(subpackets, true, false); + } + } +} diff --git a/FFXIVClassic Map Server/actors/world/WorldMaster.cs b/FFXIVClassic Map Server/actors/world/WorldMaster.cs new file mode 100644 index 00000000..a5df2016 --- /dev/null +++ b/FFXIVClassic Map Server/actors/world/WorldMaster.cs @@ -0,0 +1,44 @@ +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.lua; +using FFXIVClassic_Map_Server.packets.send.actor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.actors.world +{ + class WorldMaster : Actor + { + public WorldMaster() : base(0x5FF80001) + { + this.displayNameId = 0; + this.customDisplayName = "worldMaster"; + + this.actorName = "worldMaster"; + this.className = "WorldMaster"; + } + + public override SubPacket createScriptBindPacket(uint playerActorId) + { + List lParams; + lParams = LuaUtils.createLuaParamList("/World/WorldMaster_event", false, false, false, false, false, null); + return ActorInstantiatePacket.buildPacket(actorId, playerActorId, actorName, className, lParams); + } + + public override BasePacket getSpawnPackets(uint playerActorId) + { + List subpackets = new List(); + subpackets.Add(createAddActorPacket(playerActorId)); + subpackets.Add(createSpeedPacket(playerActorId)); + subpackets.Add(createSpawnPositonPacket(playerActorId, 0x1)); + subpackets.Add(createNamePacket(playerActorId)); + subpackets.Add(createStatePacket(playerActorId)); + subpackets.Add(createIsZoneingPacket(playerActorId)); + subpackets.Add(createScriptBindPacket(playerActorId)); + return BasePacket.createPacket(subpackets, true, false); + } + } +} diff --git a/FFXIVClassic Map Server/common/EfficientHashTables.cs b/FFXIVClassic Map Server/common/EfficientHashTables.cs new file mode 100644 index 00000000..3f94c510 --- /dev/null +++ b/FFXIVClassic Map Server/common/EfficientHashTables.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.common +{ + namespace EfficientHashTables + { + public class Efficient64bitHashTable + { + private class element + { + public ulong _key; + public T _value; + }; + private element[][] _buckets; + private uint _capacity; + + public Efficient64bitHashTable() + { + _capacity = 214373; // some prime number + _buckets = new element[_capacity][]; + } + public Efficient64bitHashTable(uint capacity) + { + _capacity = capacity; + _buckets = new element[_capacity][]; + } + + public uint hash(ulong key) + { + return (uint)(key % _capacity); + } + + public void Add(ulong key, T value) + { + uint hsh = hash(key); + element[] e; + if (_buckets[hsh] == null) + _buckets[hsh] = e = new element[1]; + else + { + foreach (var elem in _buckets[hsh]) + if (elem._key == key) + { + elem._value = value; + return; + } + e = new element[_buckets[hsh].Length + 1]; + Array.Copy(_buckets[hsh], 0, e, 1, _buckets[hsh].Length); + _buckets[hsh] = e; + } + e[0] = new element { _key = key, _value = value }; + } + + public T Get(ulong key) + { + uint hsh = hash(key); + element[] e = _buckets[hsh]; + if (e == null) return default(T); + foreach (var f in e) + if (f._key == key) + return f._value; + return default(T); + } + + public bool Has(ulong key) + { + uint hsh = hash(key); + element[] e = _buckets[hsh]; + if (e == null) return false; + foreach (var f in e) + if (f._key == key) + return true; + return false; + } + + public int Count() + { + int r = 0; + foreach (var e in _buckets) + if (e != null) + r += e.Length; + return r; + } + } + + public class Efficient32bitHashTable + { + private class element + { + public uint _key; + public T _value; + }; + private element[][] _buckets; + private uint _capacity; + + public Efficient32bitHashTable() + { + _capacity = 463; // some prime number + _buckets = new element[_capacity][]; + } + public Efficient32bitHashTable(uint capacity) + { + _capacity = capacity; + _buckets = new element[_capacity][]; + } + + public uint hash(uint key) + { + return (uint)(key % _capacity); + } + + public void Add(uint key, T value) + { + uint hsh = hash(key); + element[] e; + if (_buckets[hsh] == null) + _buckets[hsh] = e = new element[1]; + else + { + foreach (var elem in _buckets[hsh]) + if (elem._key == key) + { + elem._value = value; + return; + } + e = new element[_buckets[hsh].Length + 1]; + Array.Copy(_buckets[hsh], 0, e, 1, _buckets[hsh].Length); + _buckets[hsh] = e; + } + e[0] = new element { _key = key, _value = value }; + } + + public T Get(uint key) + { + uint hsh = hash(key); + element[] e = _buckets[hsh]; + if (e == null) return default(T); + foreach (var f in e) + if (f._key == key) + return f._value; + return default(T); + } + + public int Count() + { + int r = 0; + foreach (var e in _buckets) + if (e != null) + r += e.Length; + return r; + } + + } + } + +} diff --git a/FFXIVClassic Map Server/dataobjects/CharaInfo.cs b/FFXIVClassic Map Server/dataobjects/CharaInfo.cs deleted file mode 100644 index 62ce1240..00000000 --- a/FFXIVClassic Map Server/dataobjects/CharaInfo.cs +++ /dev/null @@ -1,314 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FFXIVClassic_Lobby_Server.common; -using System.IO; - -namespace FFXIVClassic_Lobby_Server.dataobjects -{ - class CharaInfo - { - public uint tribe = 0; - public uint size = 0; - public uint voice = 0; - public ushort skinColor = 0; - - public ushort hairStyle = 0; - public ushort hairColor = 0; - public ushort hairHighlightColor = 0; - public ushort eyeColor = 0; - public ushort characteristicsColor = 0; - - public struct FaceInfo - { - [BitfieldLength(5)] - public uint characteristics; - [BitfieldLength(3)] - public uint characteristicsColor; - [BitfieldLength(6)] - public uint type; - [BitfieldLength(2)] - public uint ears; - [BitfieldLength(2)] - public uint mouth; - [BitfieldLength(2)] - public uint features; - [BitfieldLength(3)] - public uint nose; - [BitfieldLength(3)] - public uint eyeShape; - [BitfieldLength(1)] - public uint irisSize; - [BitfieldLength(3)] - public uint eyebrows; - [BitfieldLength(2)] - public uint unknown; - } - - public uint faceType = 0; - public uint faceEyebrows = 0; - public uint faceEyeShape = 0; - public uint faceIrisSize = 0; - public uint faceNose = 0; - public uint faceMouth = 0; - public uint faceFeatures = 0; - public uint characteristics = 0; - public uint ears = 0; - - public uint guardian = 0; - public uint birthMonth = 0; - public uint birthDay = 0; - public uint currentClass = 0; - public uint currentJob = 0; - public uint allegiance = 0; - - public uint mainHand = 0; - public uint offHand = 0; - - public uint headGear = 0; - public uint bodyGear = 0; - public uint legsGear = 0; - public uint handsGear = 0; - public uint feetGear = 0; - public uint waistGear = 0; - public uint rightEarGear = 0; - public uint leftEarGear = 0; - public uint rightFingerGear = 0; - public uint leftFingerGear = 0; - - public uint currentLevel = 1; - - public static CharaInfo getFromNewCharRequest(String encoded) - { - byte[] data = Convert.FromBase64String(encoded.Replace('-', '+').Replace('_', '/')); - CharaInfo info = new CharaInfo(); - - using (MemoryStream stream = new MemoryStream(data)) - { - using (BinaryReader reader = new BinaryReader(stream)) - { - uint version = reader.ReadUInt32(); - uint unknown1 = reader.ReadUInt32(); - info.tribe = reader.ReadByte(); - info.size = reader.ReadByte(); - info.hairStyle = reader.ReadUInt16(); - info.hairHighlightColor = reader.ReadUInt16(); - info.faceType = reader.ReadByte(); - info.characteristics = reader.ReadByte(); - info.characteristicsColor = reader.ReadByte(); - - reader.ReadUInt32(); - - info.faceEyebrows = reader.ReadByte(); - info.faceIrisSize = reader.ReadByte(); - info.faceEyeShape = reader.ReadByte(); - info.faceNose = reader.ReadByte(); - info.faceFeatures = reader.ReadByte(); - info.faceMouth = reader.ReadByte(); - info.ears = reader.ReadByte(); - info.hairColor = reader.ReadUInt16(); - - reader.ReadUInt32(); - - info.skinColor = reader.ReadUInt16(); - info.eyeColor = reader.ReadUInt16(); - - info.voice = reader.ReadByte(); - info.guardian = reader.ReadByte(); - info.birthMonth = reader.ReadByte(); - info.birthDay = reader.ReadByte(); - info.currentClass = reader.ReadUInt16(); - - reader.ReadUInt32(); - reader.ReadUInt32(); - reader.ReadUInt32(); - - reader.BaseStream.Seek(0x10, SeekOrigin.Current); - - info.allegiance = reader.ReadByte(); - - } - } - - - - return info; - } - - public String buildForCharaList(DBCharacter chara) - { - byte[] data; - - mainHand = 79707136; - offHand = 32509954; - headGear = 43008; - bodyGear = 43008; - legsGear = 43008; - handsGear = 43008; - feetGear = 43008; - - using (MemoryStream stream = new MemoryStream()) - { - using (BinaryWriter writer = new BinaryWriter(stream)) - { - //Build faceinfo for later - FaceInfo faceInfo = new FaceInfo(); - faceInfo.characteristics = characteristics; - faceInfo.characteristicsColor = characteristicsColor; - faceInfo.type = faceType; - faceInfo.ears = ears; - faceInfo.features = faceFeatures; - faceInfo.eyebrows = faceEyebrows; - faceInfo.eyeShape = faceEyeShape; - faceInfo.irisSize = faceIrisSize; - faceInfo.mouth = faceMouth; - faceInfo.nose = faceNose; - - - string location1 = "prv0Inn01\0"; - string location2 = "defaultTerritory\0"; - - writer.Write((UInt32)0x000004c0); - writer.Write((UInt32)0x232327ea); - writer.Write((UInt32)System.Text.Encoding.UTF8.GetBytes(chara.name + '\0').Length); - writer.Write(System.Text.Encoding.UTF8.GetBytes(chara.name + '\0')); - writer.Write((UInt32)0x1c); - writer.Write((UInt32)0x04); - writer.Write((UInt32)getTribeModel()); - writer.Write((UInt32)size); - uint colorVal = skinColor | (uint)(hairColor << 10) | (uint)(eyeColor << 20); - writer.Write((UInt32)colorVal); - - var bitfield = PrimitiveConversion.ToUInt32(faceInfo); - - writer.Write((UInt32)bitfield); //FACE, Figure this out! - uint hairVal = hairHighlightColor | (uint)(hairStyle << 10) | (uint)(characteristicsColor << 20); - writer.Write((UInt32)hairVal); - writer.Write((UInt32)voice); - writer.Write((UInt32)mainHand); - writer.Write((UInt32)offHand); - - writer.Write((UInt32)0); - writer.Write((UInt32)0); - writer.Write((UInt32)0); - writer.Write((UInt32)0); - writer.Write((UInt32)0); - - writer.Write((UInt32)headGear); - writer.Write((UInt32)bodyGear); - writer.Write((UInt32)legsGear); - writer.Write((UInt32)handsGear); - writer.Write((UInt32)feetGear); - writer.Write((UInt32)waistGear); - - writer.Write((UInt32)0); - - writer.Write((UInt32)rightEarGear); - writer.Write((UInt32)leftEarGear); - - writer.Write((UInt32)0); - writer.Write((UInt32)0); - - writer.Write((UInt32)rightFingerGear); - writer.Write((UInt32)leftFingerGear); - - for (int i = 0; i < 0x8; i++) - writer.Write((byte)0); - - writer.Write((UInt32)1); - writer.Write((UInt32)1); - - writer.Write((byte)currentClass); - writer.Write((UInt16)currentLevel); - writer.Write((byte)currentJob); - writer.Write((UInt16)1); - writer.Write((byte)tribe); - - writer.Write((UInt32)0xe22222aa); - - writer.Write((UInt32)System.Text.Encoding.UTF8.GetBytes(location1).Length); - writer.Write(System.Text.Encoding.UTF8.GetBytes(location1)); - writer.Write((UInt32)System.Text.Encoding.UTF8.GetBytes(location2).Length); - writer.Write(System.Text.Encoding.UTF8.GetBytes(location2)); - - writer.Write((byte)guardian); - writer.Write((byte)birthMonth); - writer.Write((byte)birthDay); - - writer.Write((UInt16)0x17); - writer.Write((UInt32)4); - writer.Write((UInt32)4); - - writer.BaseStream.Seek(0x10, SeekOrigin.Current); - - writer.Write((UInt32)allegiance); - writer.Write((UInt32)allegiance); - } - - data = stream.GetBuffer(); - } - - return Convert.ToBase64String(data).Replace('+', '-').Replace('/', '_'); - } - - public static String debug() - { - byte[] bytes = File.ReadAllBytes("./packets/charaInfo.bin"); - - Console.WriteLine(Utils.ByteArrayToHex(bytes)); - - return Convert.ToBase64String(bytes).Replace('+', '-').Replace('/', '_'); - } - - public UInt32 getTribeModel() - { - switch (tribe) - { - //Hyur Midlander Male - case 1: - default: - return 1; - - //Hyur Midlander Female - case 2: - return 2; - - //Elezen Male - case 4: - case 6: - return 3; - - //Elezen Female - case 5: - case 7: - return 4; - - //Lalafell Male - case 8: - case 10: - return 5; - - //Lalafell Female - case 9: - case 11: - return 6; - - //Miqo'te Female - case 12: - case 13: - return 8; - - //Roegadyn Male - case 14: - case 15: - return 7; - - //Hyur Highlander Male - case 3: - return 9; - } - } - } -} diff --git a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs index ccddc0e7..36e1fa14 100644 --- a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs +++ b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs @@ -1,5 +1,4 @@ using FFXIVClassic_Lobby_Server; -using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic_Lobby_Server.packets; using FFXIVClassic_Map_Server.dataobjects.chara; using FFXIVClassic_Map_Server.packets.send.actor; @@ -28,8 +27,8 @@ namespace FFXIVClassic_Map_Server.dataobjects public ConnectedPlayer(uint actorId) { this.actorID = actorId; - DBCharacter chara = Database.getCharacter(actorId); - createPlayerActor(actorId, chara); + playerActor = new Player(actorId); + actorInstanceList.Add(playerActor); } public void addConnection(ClientConnection conn) @@ -89,16 +88,6 @@ namespace FFXIVClassic_Map_Server.dataobjects return playerActor; } - public void createPlayerActor(uint actorId, DBCharacter chara) - { - playerActor = new Player(actorId); - - playerActor.displayNameId = 0xFFFFFFFF; - playerActor.customDisplayName = chara.name; - playerActor.setPlayerAppearance(); - actorInstanceList.Add(playerActor); - } - public void updatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState) { /* @@ -112,8 +101,7 @@ namespace FFXIVClassic_Map_Server.dataobjects public void sendMotd() { - DBWorld world = Database.getServer(ConfigConstants.DATABASE_WORLDID); - //sendChat(world.motd); + } public void sendChat(ConnectedPlayer sender, string message, int mode) diff --git a/FFXIVClassic Map Server/dataobjects/DBWorld.cs b/FFXIVClassic Map Server/dataobjects/DBWorld.cs new file mode 100644 index 00000000..6b135ccd --- /dev/null +++ b/FFXIVClassic Map Server/dataobjects/DBWorld.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Lobby_Server.dataobjects +{ + class DBWorld + { + public ushort id; + public string address; + public ushort port; + public ushort listPosition; + public ushort population; + public string name; + public bool isActive; + public string motd; + } +} diff --git a/FFXIVClassic Map Server/dataobjects/database/DBCharacter.cs b/FFXIVClassic Map Server/dataobjects/database/DBCharacter.cs deleted file mode 100644 index 5f7c4aab..00000000 --- a/FFXIVClassic Map Server/dataobjects/database/DBCharacter.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using FFXIVClassic_Lobby_Server.common; -using FFXIVClassic_Lobby_Server.dataobjects; - -namespace FFXIVClassic_Lobby_Server -{ - class DBCharacter - { - public uint id; - public ushort slot; - public ushort serverId; - public string name; - public ushort state; - public string charaInfo; - public bool isLegacy; - public bool doRename; - public uint currentZoneId; - - public static CharaInfo EncodedToCharacter(String charaInfo) - { - charaInfo.Replace("+", "-"); - charaInfo.Replace("/", "_"); - byte[] data = System.Convert.FromBase64String(charaInfo); - - Console.WriteLine("------------Base64 printout------------------"); - Console.WriteLine(Utils.ByteArrayToHex(data)); - Console.WriteLine("------------Base64 printout------------------"); - - CharaInfo chara = new CharaInfo(); - - return chara; - } - } -} diff --git a/FFXIVClassic Map Server/dataobjects/database/DBCommands.cs b/FFXIVClassic Map Server/dataobjects/database/DBCommands.cs deleted file mode 100644 index 4730123b..00000000 --- a/FFXIVClassic Map Server/dataobjects/database/DBCommands.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace FFXIVClassic_Map_Server.dataobjects.database -{ - class DBCommands - { - public uint classId; - public uint index; - public uint commandId; - public uint recastTime; - } -} diff --git a/FFXIVClassic Map Server/dataobjects/database/DBJournal.cs b/FFXIVClassic Map Server/dataobjects/database/DBJournal.cs deleted file mode 100644 index 1ab18df9..00000000 --- a/FFXIVClassic Map Server/dataobjects/database/DBJournal.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace FFXIVClassic_Map_Server.dataobjects.database -{ - class DBJournal - { - public uint id; - public uint characterId; - public uint index; - public uint questId; - public uint type; - public bool abandoned; - public bool completed; - } -} \ No newline at end of file diff --git a/FFXIVClassic Map Server/dataobjects/database/DBPlayerData.cs b/FFXIVClassic Map Server/dataobjects/database/DBPlayerData.cs deleted file mode 100644 index edf5bffc..00000000 --- a/FFXIVClassic Map Server/dataobjects/database/DBPlayerData.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace FFXIVClassic_Map_Server.dataobjects.database -{ - class DBPlayerData - { - public int tribe; - public int guardian; - public int birthdayMonth; - public int birthdayDay; - public int initialTown; - } -} diff --git a/FFXIVClassic Map Server/dataobjects/database/DBStats.cs b/FFXIVClassic Map Server/dataobjects/database/DBStats.cs deleted file mode 100644 index 652c78df..00000000 --- a/FFXIVClassic Map Server/dataobjects/database/DBStats.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace FFXIVClassic_Map_Server.dataobjects.database -{ - class DBStats - { - public int hp; - public int hpMax; - public int mp; - public int mpMax; - public ushort[] state_mainSkill; - public int state_mainSkillLevel; - } -} diff --git a/FFXIVClassic Map Server/lua/LuaUtils.cs b/FFXIVClassic Map Server/lua/LuaUtils.cs index 4281726b..c8c8a41c 100644 --- a/FFXIVClassic Map Server/lua/LuaUtils.cs +++ b/FFXIVClassic Map Server/lua/LuaUtils.cs @@ -195,7 +195,7 @@ namespace FFXIVClassic_Map_Server foreach (object o in list) { - if (o.GetType().IsArray) + if (o != null && o.GetType().IsArray) { Array arrayO = (Array)o; foreach (object o2 in arrayO) diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs index e6dd9637..a26a4dd3 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorNamePacket.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace FFXIVClassic_Map_Server.packets.send.Actor +namespace FFXIVClassic_Map_Server.packets.send.actor { class SetActorNamePacket { @@ -23,7 +23,7 @@ namespace FFXIVClassic_Map_Server.packets.send.Actor { binWriter.Write((UInt32)displayNameID); - if (displayNameID == 0xFFFFFFFF) + if (displayNameID == 0 || displayNameID == 0xFFFFFFFF) { binWriter.Write(Encoding.ASCII.GetBytes(customName), 0, Encoding.ASCII.GetByteCount(customName) >= 0x20 ? 0x19 : Encoding.ASCII.GetByteCount(customName)); } diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs index cd61c7f4..7016fd9b 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs @@ -22,14 +22,17 @@ namespace FFXIVClassic_Map_Server.packets.send.actor private byte[] data = new byte[PACKET_SIZE - 0x20]; private bool isMore = false; + string currentTarget; + private MemoryStream mem; private BinaryWriter binWriter; - public SetActorPropetyPacket() + public SetActorPropetyPacket(string startingTarget) { mem = new MemoryStream(data); binWriter = new BinaryWriter(mem); binWriter.Seek(1, SeekOrigin.Begin); + currentTarget = startingTarget; } public void closeStreams() @@ -40,7 +43,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public bool addByte(uint id, byte value) { - if (runningByteTotal + 6 > MAXBYTES) + if (runningByteTotal + 6 + (1 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES) return false; binWriter.Write((byte)1); @@ -53,7 +56,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public bool addShort(uint id, ushort value) { - if (runningByteTotal + 7 > MAXBYTES) + if (runningByteTotal + 7 + (1 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES) return false; binWriter.Write((byte)2); @@ -66,7 +69,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public bool addInt(uint id, uint value) { - if (runningByteTotal + 9 > MAXBYTES) + if (runningByteTotal + 9 + (1 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES) return false; binWriter.Write((byte)4); @@ -79,7 +82,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public bool addBuffer(uint id, byte[] buffer) { - if (runningByteTotal + 5 + buffer.Length > MAXBYTES) + if (runningByteTotal + 5 + buffer.Length + (1 + Encoding.ASCII.GetByteCount(currentTarget)) > MAXBYTES) return false; binWriter.Write((byte)buffer.Length); @@ -90,13 +93,13 @@ namespace FFXIVClassic_Map_Server.packets.send.actor return true; } - public void addProperty(FFXIVClassic_Map_Server.dataobjects.Actor actor, string name) + public bool addProperty(FFXIVClassic_Map_Server.dataobjects.Actor actor, string name) { string[] split = name.Split('.'); int arrayIndex = 0; if (!(split[0].Equals("work") || split[0].Equals("charaWork") || split[0].Equals("playerWork") || split[0].Equals("npcWork"))) - return; + return false; Object curObj = actor; for (int i = 0; i < split.Length; i++) @@ -105,54 +108,54 @@ namespace FFXIVClassic_Map_Server.packets.send.actor if (split[i].Contains('[')) { if (split[i].LastIndexOf(']') - split[i].IndexOf('[') <= 0) - return; + return false; - arrayIndex = Convert.ToInt32(split[i].Substring(split[i].IndexOf('[') + 1, split[i].Length - split[i].LastIndexOf(']'))); + arrayIndex = Convert.ToInt32(split[i].Substring(split[i].IndexOf('[') + 1, split[i].LastIndexOf(']') - split[i].LastIndexOf('[')-1)); split[i] = split[i].Substring(0, split[i].IndexOf('[')); } FieldInfo field = curObj.GetType().GetField(split[i]); if (field == null) - return; + return false; curObj = field.GetValue(curObj); if (curObj == null) - return; + return false; } if (curObj == null) - return; + return false; else { //Array, we actually care whats inside if (curObj.GetType().IsArray) { if (((Array)curObj).Length <= arrayIndex) - return; + return false; curObj = ((Array)curObj).GetValue(arrayIndex); } if (curObj == null) - return; + return false; //Cast to the proper object and add to packet uint id = Utils.MurmurHash2(name, 0); if (curObj is bool) - addByte(id, (byte)(((bool)curObj) ? 1 : 0)); + return addByte(id, (byte)(((bool)curObj) ? 1 : 0)); else if (curObj is byte) - addByte(id, (byte)curObj); + return addByte(id, (byte)curObj); else if (curObj is ushort) - addShort(id, (ushort)curObj); - else if (curObj is short) - addShort(id, (ushort)(short)curObj); + return addShort(id, (ushort)curObj); + else if (curObj is short) + return addShort(id, (ushort)(short)curObj); else if (curObj is uint) - addInt(id, (uint)curObj); - else if (curObj is int) - addInt(id, (uint)(int)curObj); + return addInt(id, (uint)curObj); + else if (curObj is int) + return addInt(id, (uint)(int)curObj); else if (curObj is float) - addBuffer(id, BitConverter.GetBytes((float)curObj)); + return addBuffer(id, BitConverter.GetBytes((float)curObj)); else - return; + return false; } } @@ -163,10 +166,22 @@ namespace FFXIVClassic_Map_Server.packets.send.actor public void setTarget(string target) { - binWriter.Write((byte)(isMore ? 0x62 + target.Length : 0x82 + target.Length)); - binWriter.Write(Encoding.ASCII.GetBytes(target)); - runningByteTotal += (ushort)(1 + Encoding.ASCII.GetByteCount(target)); + currentTarget = target; + } + public void addTarget() + { + binWriter.Write((byte)(isMore ? 0x60 + currentTarget.Length : 0x82 + currentTarget.Length)); + binWriter.Write(Encoding.ASCII.GetBytes(currentTarget)); + runningByteTotal += (ushort)(1 + Encoding.ASCII.GetByteCount(currentTarget)); + } + + public void addTarget(string newTarget) + { + binWriter.Write((byte)(isMore ? 0x60 + currentTarget.Length : 0x82 + currentTarget.Length)); + binWriter.Write(Encoding.ASCII.GetBytes(currentTarget)); + runningByteTotal += (ushort)(1 + Encoding.ASCII.GetByteCount(currentTarget)); + currentTarget = newTarget; } public SubPacket buildPacket(uint playerActorID, uint actorID) @@ -176,7 +191,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor closeStreams(); - SubPacket packet = new SubPacket(OPCODE, playerActorID, actorID, data); + SubPacket packet = new SubPacket(OPCODE, actorID, playerActorID, data); return packet; } diff --git a/FFXIVClassic Map Server/packets/send/player/SetCompletedAchievementsPacket.cs b/FFXIVClassic Map Server/packets/send/player/SetCompletedAchievementsPacket.cs index 25479a70..054e3659 100644 --- a/FFXIVClassic Map Server/packets/send/player/SetCompletedAchievementsPacket.cs +++ b/FFXIVClassic Map Server/packets/send/player/SetCompletedAchievementsPacket.cs @@ -24,7 +24,7 @@ namespace FFXIVClassic_Map_Server.packets.send.player public const int CATEGORY_DUNGEONS = 750; public const int CATEGORY_EXPLORATION = 800; public const int CATEGORY_GRAND_COMPANY = 820; - + public const ushort OPCODE = 0x019A; public const uint PACKET_SIZE = 0xA0; @@ -48,6 +48,6 @@ namespace FFXIVClassic_Map_Server.packets.send.player return new SubPacket(OPCODE, playerActorID, playerActorID, data); } - + } } \ No newline at end of file diff --git a/FFXIVClassic Map Server/packets/send/player/SetGrandCompanyPacket.cs b/FFXIVClassic Map Server/packets/send/player/SetGrandCompanyPacket.cs index 1593fde6..5af08034 100644 --- a/FFXIVClassic Map Server/packets/send/player/SetGrandCompanyPacket.cs +++ b/FFXIVClassic Map Server/packets/send/player/SetGrandCompanyPacket.cs @@ -20,11 +20,11 @@ namespace FFXIVClassic_Map_Server.packets.send.actor using (MemoryStream mem = new MemoryStream(data)) { using (BinaryWriter binWriter = new BinaryWriter(mem)) - { - binWriter.Write((UInt16)currentAllegiance); - binWriter.Write((UInt16)rankLimsa); - binWriter.Write((UInt16)rankGridania); - binWriter.Write((UInt16)rankUldah); + { + binWriter.Write((Byte)currentAllegiance); + binWriter.Write((Byte)rankLimsa); + binWriter.Write((Byte)rankGridania); + binWriter.Write((Byte)rankUldah); } } diff --git a/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs b/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs new file mode 100644 index 00000000..ab50dab9 --- /dev/null +++ b/FFXIVClassic Map Server/utils/ActorPropertyPacketUtil.cs @@ -0,0 +1,48 @@ +using FFXIVClassic_Lobby_Server.packets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FFXIVClassic_Map_Server.packets.send.actor; +using FFXIVClassic_Map_Server.dataobjects; + +namespace FFXIVClassic_Map_Server.utils +{ + class ActorPropertyPacketUtil + { + Actor forActor; + uint playerActorId; + List subPackets = new List(); + SetActorPropetyPacket currentActorPropertyPacket; + string currentTarget; + + public ActorPropertyPacketUtil(string firstTarget, Actor forActor, uint playerActorId) + { + currentActorPropertyPacket = new SetActorPropetyPacket(firstTarget); + this.forActor = forActor; + this.playerActorId = playerActorId; + this.currentTarget = firstTarget; + } + + public void addProperty(string property) + { + if (!currentActorPropertyPacket.addProperty(forActor, property)) + { + currentActorPropertyPacket.setIsMore(true); + currentActorPropertyPacket.addTarget(); + subPackets.Add(currentActorPropertyPacket.buildPacket(playerActorId, forActor.actorId)); + currentActorPropertyPacket = new SetActorPropetyPacket(currentTarget); + } + } + + public BasePacket done() + { + currentActorPropertyPacket.addTarget(); + currentActorPropertyPacket.setIsMore(false); + subPackets.Add(currentActorPropertyPacket.buildPacket(playerActorId, forActor.actorId)); + return BasePacket.createPacket(subPackets, true, false); + } + + } +} diff --git a/FFXIVClassic Map Server/dataobjects/database/DBAppearance.cs b/FFXIVClassic Map Server/utils/CharacterUtils.cs similarity index 67% rename from FFXIVClassic Map Server/dataobjects/database/DBAppearance.cs rename to FFXIVClassic Map Server/utils/CharacterUtils.cs index 4501e490..a1ff65dd 100644 --- a/FFXIVClassic Map Server/dataobjects/database/DBAppearance.cs +++ b/FFXIVClassic Map Server/utils/CharacterUtils.cs @@ -5,49 +5,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace FFXIVClassic_Lobby_Server.dataobjects +namespace FFXIVClassic_Map_Server.utils { - class DBAppearance + class CharacterUtils { - //////////// - //Chara Info - public byte tribe = 0; - public byte size = 0; - public byte voice = 0; - public ushort skinColor = 0; - - public ushort hairStyle = 0; - public ushort hairColor = 0; - public ushort hairHighlightColor = 0; - public ushort eyeColor = 0; - public byte characteristicsColor = 0; - - public byte faceType = 0; - public byte faceEyebrows = 0; - public byte faceEyeShape = 0; - public byte faceIrisSize = 0; - public byte faceNose = 0; - public byte faceMouth = 0; - public byte faceFeatures = 0; - public byte characteristics = 0; - public byte ears = 0; - - public uint mainHand = 0; - public uint offHand = 0; - - public uint head = 0; - public uint body = 0; - public uint legs = 0; - public uint hands = 0; - public uint feet = 0; - public uint waist = 0; - public uint rightEar = 0; - public uint leftEar = 0; - public uint rightFinger = 0; - public uint leftFinger = 0; - //Chara Info - //////////// - public struct FaceInfo { [BitfieldLength(5)] @@ -73,8 +34,8 @@ namespace FFXIVClassic_Lobby_Server.dataobjects [BitfieldLength(2)] public uint unknown; } - - public FaceInfo getFaceInfo() + + public static FaceInfo getFaceInfo(byte characteristics, byte characteristicsColor, byte faceType, byte ears, byte faceMouth, byte faceFeatures, byte faceNose, byte faceEyeShape, byte faceIrisSize, byte faceEyebrows) { FaceInfo faceInfo = new FaceInfo(); faceInfo.characteristics = characteristics; diff --git a/FFXIVClassic Map Server/utils/SQLGeneration.cs b/FFXIVClassic Map Server/utils/SQLGeneration.cs new file mode 100644 index 00000000..e24a9b7d --- /dev/null +++ b/FFXIVClassic Map Server/utils/SQLGeneration.cs @@ -0,0 +1,362 @@ +using FFXIVClassic_Lobby_Server; +using FFXIVClassic_Map_Server.packets.send.player; +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.utils +{ + class SQLGeneration + { + public static void generateItems() + { + + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load Last 5 Completed + string query = @" + INSERT INTO gamedata_items VALUES (@id, @displayNameId, NULL)"; + + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", 100); + cmd.Parameters.AddWithValue("@displayNameId", 100); + + cmd.Prepare(); + + string line, line2; + Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled); + System.IO.StreamReader file = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\actorclass.csv"); + while ((line = file.ReadLine()) != null) + { + MatchCollection matches = csvSplit.Matches(line); + + uint id; + uint nameId; + + try + { + id = UInt32.Parse(matches[0].Value.Trim(',')); + nameId = UInt32.Parse(matches[6].Value.Trim(',')); + + } + catch (FormatException e) + { continue; } + + cmd.Parameters["@id"].Value = id; + cmd.Parameters["@displayNameId"].Value = nameId; + + Console.WriteLine("Wrote: {0} : {1}", id, nameId); + cmd.ExecuteNonQuery(); + + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + } + + public static void generateZones() + { + + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load Last 5 Completed + string query = @" + INSERT INTO server_zones VALUES (@id, NULL, @placename, false, false, false, false)"; + + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", 100); + cmd.Parameters.AddWithValue("@placename", ""); + + cmd.Prepare(); + + Dictionary placenames = new Dictionary(); + + string line2; + Regex csvSplit2 = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled); + System.IO.StreamReader file2 = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\xtx_placeName.csv"); + while ((line2 = file2.ReadLine()) != null) + { + MatchCollection matches = csvSplit2.Matches(line2); + + uint id; + string name; + + try + { + id = UInt32.Parse(matches[0].Value.Trim(',')); + name = matches[2].Value.Trim(','); + + } + catch (FormatException e) + { continue; } + + placenames.Add(id, name); + + } + + string line; + Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled); + System.IO.StreamReader file = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\_zoneParam.csv"); + while ((line = file.ReadLine()) != null) + { + MatchCollection matches = csvSplit.Matches(line); + + uint id; + uint pId; + + try + { + id = UInt32.Parse(matches[0].Value.Trim(',')); + pId = UInt32.Parse(matches[1].Value.Trim(',')); + } + catch (FormatException e) + { continue; } + + cmd.Parameters["@id"].Value = id; + + cmd.Parameters["@placename"].Value = placenames[pId]; + + Console.WriteLine("Wrote: {0}", id); + cmd.ExecuteNonQuery(); + + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + } + + public static void generateActors() + { + + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load Last 5 Completed + string query = @" + INSERT INTO gamedata_actor_templates VALUES (@id, @displayNameId, NULL)"; + + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", 100); + cmd.Parameters.AddWithValue("@displayNameId", 100); + + cmd.Prepare(); + + string line, line2; + Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled); + System.IO.StreamReader file = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\actorclass.csv"); + while ((line = file.ReadLine()) != null) + { + MatchCollection matches = csvSplit.Matches(line); + + uint id; + uint nameId; + + try + { + id = UInt32.Parse(matches[0].Value.Trim(',')); + nameId = UInt32.Parse(matches[6].Value.Trim(',')); + + } + catch (FormatException e) + { continue; } + + cmd.Parameters["@id"].Value = id; + cmd.Parameters["@displayNameId"].Value = nameId; + + Console.WriteLine("Wrote: {0} : {1}", id, nameId); + cmd.ExecuteNonQuery(); + + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + } + + public static void generateActorAppearance() + { + uint NUMFIELDS = 39; + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load Last 5 Completed + string query = @" + INSERT INTO gamedata_actor_appearance VALUES (@id, "; + + for (int i = 0; i < NUMFIELDS-1; i++) + query += "@v"+i+", "; + + query += "@v" + (NUMFIELDS-1) + ")"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", 0); + + for (int i = 0; i < NUMFIELDS; i++) + cmd.Parameters.AddWithValue("@v" + i, 100); + + cmd.Prepare(); + + string line; + Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled); + //System.IO.StreamReader file = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\actorclass.csv"); + System.IO.StreamReader file = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\actorclass_graphic.csv"); + while ((line = file.ReadLine()) != null) + { + MatchCollection matches = csvSplit.Matches(line); + + uint id; + + try + { + id = UInt32.Parse(matches[0].Value.Trim(',')); + + for (int i = 0; i < NUMFIELDS; i++) + cmd.Parameters["@v" + i].Value = matches[i + 7].Value.Trim(','); + + + } + catch (FormatException e) + { continue; } + + cmd.Parameters["@id"].Value = id; + + Console.WriteLine("Wrote: {0}", id); + cmd.ExecuteNonQuery(); + + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + + + } + + public static void generateAchievementIds() + { + + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + + //Load Last 5 Completed + string query = @" + INSERT INTO gamedata_achievements VALUES (@id, @name, @otherId, @rewardPoints)"; + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@id", 100); + cmd.Parameters.AddWithValue("@name", "Battle"); + cmd.Parameters.AddWithValue("@otherId", 0); + cmd.Parameters.AddWithValue("@rewardPoints", 0); + cmd.Prepare(); + + int otherId = 1; + string line, line2; + Regex csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled); + System.IO.StreamReader file = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\achievement.csv"); + System.IO.StreamReader file2 = new System.IO.StreamReader("D:\\Coding\\FFXIV Related\\FFXIV Tool\\2012.09.19.0001.decode.csv\\xtx_achievement.csv"); + while ((line = file.ReadLine()) != null) + { + line2 = file2.ReadLine(); + MatchCollection matches = csvSplit.Matches(line); + MatchCollection matches2 = csvSplit.Matches(line2); + uint id; + string name; + uint points; + try + { + id = UInt32.Parse(matches2[0].Value.Trim(',')); + name = matches2[9].Value.Trim(','); + points = UInt32.Parse(matches[3].Value.Trim(',')); + } + catch (FormatException e) + { continue; } + + if (id == 100) + otherId = SetCompletedAchievementsPacket.CATEGORY_BATTLE; + else if (id == 200) + otherId = SetCompletedAchievementsPacket.CATEGORY_CHARACTER; + else if (id == 400) + otherId = SetCompletedAchievementsPacket.CATEGORY_CURRENCY; + else if (id == 500) + otherId = SetCompletedAchievementsPacket.CATEGORY_ITEMS; + else if (id == 600) + otherId = SetCompletedAchievementsPacket.CATEGORY_SYNTHESIS; + else if (id == 700) + otherId = SetCompletedAchievementsPacket.CATEGORY_GATHERING; + else if (id == 900) + otherId = SetCompletedAchievementsPacket.CATEGORY_MATERIA; + else if (id == 1000) + otherId = SetCompletedAchievementsPacket.CATEGORY_QUESTS; + else if (id == 1200) + otherId = SetCompletedAchievementsPacket.CATEGORY_SEASONAL_EVENTS; + else if (id == 1300) + otherId = SetCompletedAchievementsPacket.CATEGORY_DUNGEONS; + else if (id == 1400) + otherId = SetCompletedAchievementsPacket.CATEGORY_EXPLORATION; + else if (id == 1500) + otherId = SetCompletedAchievementsPacket.CATEGORY_GRAND_COMPANY; + + Console.WriteLine("Wrote: {0} : {1} : {2} : {3}", id, name, otherId, points); + cmd.Parameters["@id"].Value = id; + cmd.Parameters["@name"].Value = name; + cmd.Parameters["@otherId"].Value = otherId; + cmd.Parameters["@rewardPoints"].Value = points; + cmd.ExecuteNonQuery(); + + otherId++; + } + } + catch (MySqlException e) + { Console.WriteLine(e); } + finally + { + conn.Dispose(); + } + } + + + } + } +}