1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-24 13:47:46 +00:00

Merge branch 'inventory_refactor' into develop

# Conflicts:
#	FFXIVClassic Map Server/Database.cs
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
#	FFXIVClassic Map Server/WorldManager.cs
#	FFXIVClassic Map Server/actors/area/Area.cs
#	FFXIVClassic Map Server/actors/area/Zone.cs
#	FFXIVClassic Map Server/actors/chara/Character.cs
#	FFXIVClassic Map Server/actors/chara/npc/Npc.cs
#	FFXIVClassic Map Server/actors/chara/player/Inventory.cs
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
#	FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
#	FFXIVClassic Map Server/lua/LuaEngine.cs
#	FFXIVClassic Map Server/packets/send/Actor/AddActorPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/DeleteAllActorsPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorStatePacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorStatusAllPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorStatusPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/_0x132Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/BattleAction.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX10Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX18Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/CommandResultX00Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/events/SetEmoteEventCondition.cs
#	FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX08Packet.cs
#	data/scripts/commands/gm/giveitem.lua
This commit is contained in:
Filip Maj 2019-05-06 15:59:09 -04:00
commit bcb609e4f6
202 changed files with 2713 additions and 1040 deletions

View file

@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following

View file

@ -1,12 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using NLog;
using System.Data;
using System.Data.Common;
using NLog;
namespace FFXIVClassic.Common
{

View file

@ -1,6 +1,5 @@
using System;
using System.Runtime.InteropServices;
using FFXIVClassic.Common;
using NLog;
using NLog.Targets;

View file

@ -139,6 +139,12 @@ namespace FFXIVClassic.Common
return input;
}
public static ushort SwapEndian(ushort input)
{
return (ushort)(((input << 8) & 0xff00) |
((input >> 8) & 0x00ff));
}
public static uint MurmurHash2(string key, uint seed)
{
// 'm' and 'r' are mixing constants generated offline.

View file

@ -4,7 +4,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using FFXIVClassic_Lobby_Server.utils;
using FFXIVClassic.Common;
namespace FFXIVClassic_Lobby_Server
{

View file

@ -2,8 +2,6 @@
using System.Diagnostics;
using System.Threading;
using MySql.Data.MySqlClient;
using System.Reflection;
using FFXIVClassic.Common;
using NLog;
namespace FFXIVClassic_Lobby_Server
{

View file

@ -5,7 +5,6 @@ using System.Net.Sockets;
using System.Threading;
using FFXIVClassic.Common;
using NLog;
namespace FFXIVClassic_Lobby_Server
{

View file

@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System.IO;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.Actors;

View file

@ -1,9 +1,6 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using MoonSharp.Interpreter.Interop;
using System.Linq;
using System.Net;

View file

@ -1111,12 +1111,12 @@ namespace FFXIVClassic_Map_Server
}
}
player.GetInventory(Inventory.NORMAL).InitList(GetInventory(player, 0, Inventory.NORMAL));
player.GetInventory(Inventory.KEYITEMS).InitList(GetInventory(player, 0, Inventory.KEYITEMS));
player.GetInventory(Inventory.CURRENCY_CRYSTALS).InitList(GetInventory(player, 0, Inventory.CURRENCY_CRYSTALS));
player.GetInventory(Inventory.BAZAAR).InitList(GetInventory(player, 0, Inventory.BAZAAR));
player.GetInventory(Inventory.MELDREQUEST).InitList(GetInventory(player, 0, Inventory.MELDREQUEST));
player.GetInventory(Inventory.LOOT).InitList(GetInventory(player, 0, Inventory.LOOT));
player.GetItemPackage(ItemPackage.NORMAL).InitList(GetItemPackage(player, 0, ItemPackage.NORMAL));
player.GetItemPackage(ItemPackage.KEYITEMS).InitList(GetItemPackage(player, 0, ItemPackage.KEYITEMS));
player.GetItemPackage(ItemPackage.CURRENCY_CRYSTALS).InitList(GetItemPackage(player, 0, ItemPackage.CURRENCY_CRYSTALS));
player.GetItemPackage(ItemPackage.BAZAAR).InitList(GetBazaar(player));
player.GetItemPackage(ItemPackage.MELDREQUEST).InitList(GetItemPackage(player, 0, ItemPackage.MELDREQUEST));
player.GetItemPackage(ItemPackage.LOOT).InitList(GetItemPackage(player, 0, ItemPackage.LOOT));
player.GetEquipment().SetEquipment(GetEquipment(player, player.charaWork.parameterSave.state_mainSkill[0]));
}
@ -1159,7 +1159,7 @@ namespace FFXIVClassic_Map_Server
{
ushort equipSlot = reader.GetUInt16(0);
ulong uniqueItemId = reader.GetUInt16(1);
InventoryItem item = player.GetInventory(Inventory.NORMAL).GetItemByUniqueId(uniqueItemId);
InventoryItem item = player.GetItemPackage(ItemPackage.NORMAL).GetItemByUniqueId(uniqueItemId);
equipment[equipSlot] = item;
}
}
@ -1435,7 +1435,8 @@ namespace FFXIVClassic_Map_Server
}
return slot;
}
public static List<InventoryItem> GetInventory(Player player, uint slotOffset, uint type)
public static List<InventoryItem> GetItemPackage(Player player, uint slotOffset, uint type)
{
List<InventoryItem> items = new List<InventoryItem>();
@ -1449,19 +1450,29 @@ namespace FFXIVClassic_Map_Server
SELECT
serverItemId,
itemId,
server_items_modifiers.id AS modifierId,
quantity,
itemType,
quality,
durability,
spiritBind,
mainQuality,
subQuality1,
subQuality2,
subQuality3,
param1,
param2,
param3,
spiritbind,
materia1,
materia2,
materia3,
materia4,
materia5
FROM characters_inventory
INNER JOIN server_items ON serverItemId = server_items.id
WHERE characterId = @charId AND inventoryType = @type";
LEFT JOIN server_items_modifiers ON server_items.id = server_items_modifiers.id
WHERE characterId = @charId AND itemPackage = @type";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.actorId);
@ -1476,21 +1487,15 @@ namespace FFXIVClassic_Map_Server
uint itemId = reader.GetUInt32("itemId");
int quantity = reader.GetInt32("quantity");
byte itemType = reader.GetByte("itemType");
byte qualityNumber = reader.GetByte("quality");
int durability = reader.GetInt32("durability");
ushort spiritBind = reader.GetUInt16("spiritBind");
bool hasModifier = !reader.IsDBNull(reader.GetOrdinal("modifierId"));
InventoryItem.ItemModifier modifier = null;
byte materia1 = reader.GetByte("materia1");
byte materia2 = reader.GetByte("materia2");
byte materia3 = reader.GetByte("materia3");
byte materia4 = reader.GetByte("materia4");
byte materia5 = reader.GetByte("materia5");
if (hasModifier)
modifier = new InventoryItem.ItemModifier(reader);
InventoryItem item = new InventoryItem(uniqueId, itemId, quantity, itemType, qualityNumber, durability, spiritBind, materia1, materia2, materia3, materia4, materia5);
item.slot = slot;
slot++;
InventoryItem item = new InventoryItem(uniqueId, Server.GetItemGamedata(itemId), quantity, qualityNumber, modifier);
items.Add(item);
}
}
@ -1508,6 +1513,247 @@ namespace FFXIVClassic_Map_Server
return items;
}
public static bool CreateBazaarEntry(Player owner, InventoryItem reward, InventoryItem seek, int rewardAmount, int seekAmount, byte bazaarMode, int sellPrice = 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 = @"
INSERT INTO characters_inventory_bazaar
(characterId, rewardId, seekId, rewardAmount, seekAmount, bazaarMode, sellPrice)
VALUES
(@characterId, @rewardId, @seekId, @rewardAmount, @seekAmount, @bazaarMode, @sellPrice);
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@characterId", owner.actorId);
cmd.Parameters.AddWithValue("@rewardId", reward.uniqueId);
cmd.Parameters.AddWithValue("@seekId", seek.uniqueId);
cmd.Parameters.AddWithValue("@rewardAmount", rewardAmount);
cmd.Parameters.AddWithValue("@seekAmount", seekAmount);
cmd.Parameters.AddWithValue("@bazaarMode", bazaarMode);
cmd.Parameters.AddWithValue("@sellPrice", sellPrice);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
return false;
}
finally
{
conn.Dispose();
}
}
return true;
}
public static void ClearBazaarEntry(Player owner, InventoryItem reward)
{
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}; Allow User Variables=True", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{
try
{
conn.Open();
string query = @"
DELETE FROM characters_inventory_bazaar
WHERE characterId = @charId and rewardId = @rewardId;
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", owner.actorId);
cmd.Parameters.AddWithValue("@rewardId", reward.uniqueId);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
}
public static List<InventoryItem> GetBazaar(Player player)
{
List<InventoryItem> rewardItems = new List<InventoryItem>();
Dictionary<ulong, InventoryItem> seekItems = new Dictionary<ulong, InventoryItem>();
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
rewardId,
seekId,
rewardAmount,
bazaarMode,
sellPrice,
itemId,
server_items_modifiers.id AS modifierId,
quantity,
quality,
durability,
mainQuality,
subQuality1,
subQuality2,
subQuality3,
param1,
param2,
param3,
spiritbind,
materia1,
materia2,
materia3,
materia4,
materia5
FROM characters_inventory_bazaar
INNER JOIN server_items ON rewardId = server_items.id
LEFT JOIN server_items_modifiers ON server_items.id = server_items_modifiers.id
WHERE characterId = @charaId";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charaId", player.actorId);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
uint uniqueId = reader.GetUInt32("rewardId");
uint itemId = reader.GetUInt32("itemId");
int quantity = reader.GetInt32("quantity");
byte qualityNumber = reader.GetByte("quality");
bool hasModifier = !reader.IsDBNull(reader.GetOrdinal("modifierId"));
InventoryItem.ItemModifier modifier = null;
if (hasModifier)
modifier = new InventoryItem.ItemModifier(reader);
InventoryItem item = new InventoryItem(uniqueId, Server.GetItemGamedata(itemId), quantity, qualityNumber, modifier);
byte bazaarMode = reader.GetByte("bazaarMode");
if (bazaarMode == InventoryItem.TYPE_SINGLE || bazaarMode == InventoryItem.TYPE_MULTI || bazaarMode == InventoryItem.TYPE_STACK)
{
uint price = (uint)reader.GetInt32("sellPrice");
item.SetDealing(bazaarMode, (int)price);
}
else
{
uint seekId = reader.GetUInt32("seekId");
item.SetDealingAttached(bazaarMode, seekId);
}
rewardItems.Add(item);
}
}
string query2 = @"
SELECT
seekId,
seekAmount,
sellPrice,
itemId,
server_items_modifiers.id AS modifierId,
quantity,
quality,
durability,
mainQuality,
subQuality1,
subQuality2,
subQuality3,
param1,
param2,
param3,
spiritbind,
materia1,
materia2,
materia3,
materia4,
materia5
FROM characters_inventory_bazaar
INNER JOIN server_items ON seekId = server_items.id
LEFT JOIN server_items_modifiers ON server_items.id = server_items_modifiers.id
WHERE characterId = @charaId and bazaarMode != 11 and bazaarMode != 12 and bazaarMode != 13";
MySqlCommand cmd2 = new MySqlCommand(query2, conn);
cmd2.Parameters.AddWithValue("@charaId", player.actorId);
using (MySqlDataReader reader = cmd2.ExecuteReader())
{
while (reader.Read())
{
uint uniqueId = reader.GetUInt32("seekId");
uint itemId = reader.GetUInt32("itemId");
int quantity = reader.GetInt32("quantity");
byte qualityNumber = reader.GetByte("quality");
bool hasModifier = !reader.IsDBNull(reader.GetOrdinal("modifierId"));
InventoryItem.ItemModifier modifier = null;
if (hasModifier)
modifier = new InventoryItem.ItemModifier(reader);
InventoryItem item = new InventoryItem(uniqueId, Server.GetItemGamedata(itemId), quantity, qualityNumber, modifier);
item.SetHasAttached(true);
seekItems.Add(uniqueId, item);
}
}
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
List<InventoryItem> items = new List<InventoryItem>();
ushort slot = 0;
foreach (InventoryItem reward in rewardItems)
{
if (reward.dealingMode == InventoryItem.DEALINGMODE_PRICED)
{
reward.slot = slot++;
items.Add(reward);
}
else
{
if (seekItems.ContainsKey(reward.GetAttached()))
{
reward.slot = slot++;
items.Add(reward);
InventoryItem seek = seekItems[reward.GetAttached()];
seek.slot = slot++;
items.Add(seek);
reward.SetAttachedIndex(7, seek.slot);
}
}
}
return items;
}
public static List<InventoryItem> GetInventory(Retainer retainer, uint type)
{
List<InventoryItem> items = new List<InventoryItem>();
@ -1522,22 +1768,32 @@ namespace FFXIVClassic_Map_Server
SELECT
serverItemId,
itemId,
server_items_modifiers.id AS modifierId,
quantity,
itemType,
quality,
durability,
spiritBind,
mainQuality,
subQuality1,
subQuality2,
subQuality3,
param1,
param2,
param3,
spiritbind,
materia1,
materia2,
materia3,
materia4,
materia5
FROM retainers_inventory
INNER JOIN server_items ON serverItemId = server_items.id
WHERE retainerId = @retainerId AND inventoryType = @type";
LEFT JOIN server_items_modifiers ON server_items.id = server_items_modifiers.id
WHERE retainerId = @retainerId AND itemPackage = @type";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@retainerId", retainer.getRetainerId());
cmd.Parameters.AddWithValue("@retainerId", retainer.GetRetainerId());
cmd.Parameters.AddWithValue("@type", type);
ushort slot = 0;
@ -1549,21 +1805,15 @@ namespace FFXIVClassic_Map_Server
uint itemId = reader.GetUInt32("itemId");
int quantity = reader.GetInt32("quantity");
byte itemType = reader.GetByte("itemType");
byte qualityNumber = reader.GetByte("quality");
int durability = reader.GetInt32("durability");
ushort spiritBind = reader.GetUInt16("spiritBind");
bool hasModifier = !reader.IsDBNull(reader.GetOrdinal("modifierId"));
InventoryItem.ItemModifier modifier = null;
byte materia1 = reader.GetByte("materia1");
byte materia2 = reader.GetByte("materia2");
byte materia3 = reader.GetByte("materia3");
byte materia4 = reader.GetByte("materia4");
byte materia5 = reader.GetByte("materia5");
if (hasModifier)
modifier = new InventoryItem.ItemModifier(reader);
InventoryItem item = new InventoryItem(uniqueId, itemId, quantity, itemType, qualityNumber, durability, spiritBind, materia1, materia2, materia3, materia4, materia5);
item.slot = slot;
slot++;
InventoryItem item = new InventoryItem(uniqueId, Server.GetItemGamedata(itemId), quantity, qualityNumber, modifier);
items.Add(item);
}
}
@ -1581,7 +1831,7 @@ namespace FFXIVClassic_Map_Server
return items;
}
public static InventoryItem CreateItem(uint itemId, int quantity, byte quality, byte itemType, int durability)
public static InventoryItem CreateItem(uint itemId, int quantity, byte quality, InventoryItem.ItemModifier modifiers = null)
{
InventoryItem insertedItem = null;
@ -1595,21 +1845,33 @@ namespace FFXIVClassic_Map_Server
string query = @"
INSERT INTO server_items
(itemId, quality, itemType, durability)
(itemId, quantity, quality)
VALUES
(@itemId, @quality, @itemType, @durability);
(@itemId, @quantity, @quality);
";
string query2 = @"
INSERT INTO server_items_modifiers
(id, durability)
VALUES
(@id, @durability);
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@itemId", itemId);
cmd.Parameters.AddWithValue("@quantity", quantity);
cmd.Parameters.AddWithValue("@quality", quality);
cmd.Parameters.AddWithValue("@itemType", itemType);
cmd.Parameters.AddWithValue("@durability", durability);
cmd.ExecuteNonQuery();
insertedItem = new InventoryItem((uint)cmd.LastInsertedId, itemId, quantity, itemType, quality, durability, 0, 0, 0, 0, 0, 0);
insertedItem = new InventoryItem((uint)cmd.LastInsertedId, Server.GetItemGamedata(itemId), quantity, quality, modifiers);
if (modifiers != null)
{
MySqlCommand cmd2 = new MySqlCommand(query2, conn);
cmd2.Parameters.AddWithValue("@id", insertedItem.uniqueId);
cmd2.Parameters.AddWithValue("@durability", modifiers.durability);
cmd2.ExecuteNonQuery();
}
}
catch (MySqlException e)
{
@ -1634,17 +1896,16 @@ namespace FFXIVClassic_Map_Server
string query = @"
INSERT INTO characters_inventory
(characterId, inventoryType, serverItemId, quantity)
(characterId, itemPackage, serverItemId)
VALUES
(@charId, @inventoryType, @serverItemId, @quantity)
(@charId, @itemPackage, @serverItemId)
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@serverItemId", addedItem.uniqueId);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.Parameters.AddWithValue("@inventoryType", type);
cmd.Parameters.AddWithValue("@quantity", addedItem.quantity);
cmd.Parameters.AddWithValue("@itemPackage", type);
cmd.ExecuteNonQuery();
}
@ -1659,7 +1920,9 @@ namespace FFXIVClassic_Map_Server
}
}
public static void SetQuantity(Player player, ulong serverItemId, int quantity)
public static void SetQuantity(ulong serverItemId, int quantity)
{
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)))
{
@ -1668,13 +1931,12 @@ namespace FFXIVClassic_Map_Server
conn.Open();
string query = @"
UPDATE characters_inventory
UPDATE server_items
SET quantity = @quantity
WHERE characterId = @charId and serverItemId = @serverItemId;
WHERE id = @serverItemId;
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.Parameters.AddWithValue("@serverItemId", serverItemId);
cmd.Parameters.AddWithValue("@quantity", quantity);
cmd.ExecuteNonQuery();
@ -1720,7 +1982,6 @@ namespace FFXIVClassic_Map_Server
conn.Dispose();
}
}
}
public static void AddItem(Retainer retainer, InventoryItem addedItem, uint type)
@ -1733,17 +1994,16 @@ namespace FFXIVClassic_Map_Server
string query = @"
INSERT INTO retainers_inventory
(retainerId, inventoryType, serverItemId, quantity)
(retainerId, itemPackage, serverItemId)
VALUES
(@retainerId, @inventoryType, @serverItemId, @quantity)
(@retainerId, @itemPackage, @serverItemId)
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@serverItemId", addedItem.uniqueId);
cmd.Parameters.AddWithValue("@retainerId", retainer.getRetainerId());
cmd.Parameters.AddWithValue("@inventoryType", type);
cmd.Parameters.AddWithValue("@quantity", addedItem.quantity);
cmd.Parameters.AddWithValue("@retainerId", retainer.GetRetainerId());
cmd.Parameters.AddWithValue("@itemPackage", type);
cmd.ExecuteNonQuery();
}
@ -1758,39 +2018,6 @@ namespace FFXIVClassic_Map_Server
}
}
public static void SetQuantity(Retainer retainer, ulong serverItemId, int quantity)
{
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 = @"
UPDATE retainers_inventory
SET quantity = @quantity
WHERE retainerId = @retainerId and serverItemId = @serverItemId;
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@retainerId", retainer.getRetainerId());
cmd.Parameters.AddWithValue("@serverItemId", serverItemId);
cmd.Parameters.AddWithValue("@quantity", quantity);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
}
public static void RemoveItem(Retainer retainer, ulong serverItemId)
{
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}; Allow User Variables=True", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
@ -1805,7 +2032,7 @@ namespace FFXIVClassic_Map_Server
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@retainerId", retainer.getRetainerId());
cmd.Parameters.AddWithValue("@retainerId", retainer.GetRetainerId());
cmd.Parameters.AddWithValue("@serverItemId", serverItemId);
cmd.ExecuteNonQuery();
@ -2619,7 +2846,7 @@ namespace FFXIVClassic_Map_Server
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charaId", player.actorId);
cmd.Parameters.AddWithValue("@retainerIndex", retainerIndex-1);
cmd.Parameters.AddWithValue("@retainerIndex", retainerIndex - 1);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
@ -2651,5 +2878,85 @@ namespace FFXIVClassic_Map_Server
}
}
public static void PlayerCharacterUpdateClassLevel(Player player, byte classId, short level)
{
string query;
MySqlCommand cmd;
string[] classNames = {
"",
"",
"pug",
"gla",
"mrd",
"",
"",
"arc",
"lnc",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"thm",
"cnj",
"",
"",
"",
"",
"",
"crp",
"bsm",
"arm",
"gsm",
"ltw",
"wvr",
"alc",
"cul",
"",
"",
"min",
"btn",
"fsh"
};
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();
query = String.Format(@"
UPDATE characters_class_levels
SET
{0}=@level
WHERE
characterId = @characterId", classNames[classId]);
cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@level", level);
cmd.Parameters.AddWithValue("@characterId", player.actorId);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
}
}
}

View file

@ -150,23 +150,25 @@
<Compile Include="actors\EventList.cs" />
<Compile Include="actors\group\GLContentGroup.cs" />
<Compile Include="actors\group\ContentGroup.cs" />
<Compile Include="actors\group\TradeGroup.cs" />
<Compile Include="actors\group\RetainerMeetingRelationGroup.cs" />
<Compile Include="actors\group\Work\ContentGroupWork.cs" />
<Compile Include="actors\group\Work\GlobalTemp.cs" />
<Compile Include="actors\group\Group.cs" />
<Compile Include="actors\group\MonsterParty.cs" />
<Compile Include="actors\group\Party.cs" />
<Compile Include="actors\group\Relation.cs" />
<Compile Include="actors\group\work\GroupGlobalSave.cs" />
<Compile Include="actors\group\work\GroupGlobalTemp.cs" />
<Compile Include="actors\group\work\GroupMemberSave.cs" />
<Compile Include="actors\group\work\PartyWork.cs" />
<Compile Include="actors\group\work\RelationWork.cs" />
<Compile Include="actors\group\RelationGroup.cs" />
<Compile Include="actors\group\Work\GroupGlobalSave.cs" />
<Compile Include="actors\group\Work\GroupGlobalTemp.cs" />
<Compile Include="actors\group\Work\GroupMemberSave.cs" />
<Compile Include="actors\group\Work\PartyWork.cs" />
<Compile Include="actors\group\Work\RelationWork.cs" />
<Compile Include="actors\judge\Judge.cs" />
<Compile Include="actors\quest\Quest.cs" />
<Compile Include="actors\StaticActors.cs" />
<Compile Include="actors\world\WorldMaster.cs" />
<Compile Include="dataobjects\GuildleveData.cs" />
<Compile Include="dataobjects\TradeTransaction.cs" />
<Compile Include="dataobjects\ZoneConnection.cs" />
<Compile Include="CommandProcessor.cs" />
<Compile Include="ConfigConstants.cs" />
@ -202,6 +204,7 @@
<Compile Include="packets\receive\HandshakePacket.cs" />
<Compile Include="packets\receive\CountdownRequestPacket.cs" />
<Compile Include="packets\receive\LangaugeCodePacket.cs" />
<Compile Include="packets\receive\UpdateItemPackagePacket.cs" />
<Compile Include="packets\receive\ParameterDataRequestPacket.cs" />
<Compile Include="packets\receive\recruitment\RecruitmentDetailsRequestPacket.cs" />
<Compile Include="packets\receive\recruitment\RecruitmentSearchRequestPacket.cs" />
@ -361,6 +364,7 @@
<Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\ErrorPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\PartySyncPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\LinkshellResultPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\SessionEndPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\CreateLinkshellPacket.cs" />

View file

@ -1,9 +1,6 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.receive;
using FFXIVClassic_Map_Server.packets.send;
@ -88,6 +85,11 @@ namespace FFXIVClassic_Map_Server
PartySyncPacket partySyncPacket = new PartySyncPacket(subpacket.data);
Server.GetWorldManager().PartyMemberListRecieved(partySyncPacket);
break;
//World Server - Linkshell Creation Result
case 0x1025:
LinkshellResultPacket lsResult = new LinkshellResultPacket(subpacket.data);
LuaEngine.GetInstance().OnSignal("ls_result", lsResult.resultCode);
break;
//Ping
case 0x0001:
//subpacket.DebugPrintSubPacket();
@ -176,11 +178,6 @@ namespace FFXIVClassic_Map_Server
Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
session.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
session.GetActor().currentEventName = eventStart.triggerName;
if (ownerActor == null)
{
//Is it your retainer?
@ -188,7 +185,7 @@ namespace FFXIVClassic_Map_Server
ownerActor = session.GetActor().currentSpawnedRetainer;
//Is it a instance actor?
if (ownerActor == null)
ownerActor = session.GetActor().zone.FindActorInArea(session.GetActor().currentEventOwner);
ownerActor = session.GetActor().zone.FindActorInArea(eventStart.scriptOwnerActorID);
if (ownerActor == null)
{
//Is it a Director?
@ -246,6 +243,17 @@ namespace FFXIVClassic_Map_Server
if (paramRequest.paramName.Equals("charaWork/exp"))
session.GetActor().SendCharaExpInfo();
break;
//Item Package Request
case 0x0131:
UpdateItemPackagePacket packageRequest = new UpdateItemPackagePacket(subpacket.data);
if (Server.GetWorldManager().GetActorInWorld(packageRequest.actorID) != null)
{
((Character)Server.GetWorldManager().GetActorInWorld(packageRequest.actorID)).SendItemPackage(session.GetActor(), packageRequest.packageId);
break;
}
if (session.GetActor().GetSpawnedRetainer() != null && session.GetActor().GetSpawnedRetainer().actorId == packageRequest.actorID)
session.GetActor().GetSpawnedRetainer().SendItemPackage(session.GetActor(), packageRequest.packageId);
break;
//Group Created Confirm
case 0x0133:
GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data);

View file

@ -1,15 +1,7 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Text;
using MySql.Data.MySqlClient;
using System.Reflection;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic.Common;
using NLog;
using NLog.Targets;
using NLog.Targets.Wrappers;
using NLog.Config;
namespace FFXIVClassic_Map_Server
{

View file

@ -6,7 +6,6 @@ using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
namespace FFXIVClassic_Map_Server
{

View file

@ -1,30 +1,24 @@
using FFXIVClassic_Map_Server;
using FFXIVClassic.Common;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.packets.send.login;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.WorldPackets.Receive;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group;
using System.Threading;
using System.Diagnostics;
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.actors.chara.ai;
using FFXIVClassic_Map_Server.actors.chara;
using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.actors.chara.player;
namespace FFXIVClassic_Map_Server
{
@ -51,9 +45,12 @@ namespace FFXIVClassic_Map_Server
private const int MILIS_LOOPTIME = 333;
private Timer mZoneTimer;
//Content Groups
//Zone Server Groups
public Dictionary<ulong, Group> mContentGroups = new Dictionary<ulong, Group>();
public Dictionary<ulong, RelationGroup> mRelationGroups = new Dictionary<ulong, RelationGroup>();
public Dictionary<ulong, TradeGroup> mTradeGroups = new Dictionary<ulong, TradeGroup>();
private Object groupLock = new Object();
private Object tradeLock = new Object();
public ulong groupIndexId = 1;
public WorldManager(Server server)
@ -1033,8 +1030,6 @@ namespace FFXIVClassic_Map_Server
player.playerSession.LockUpdates(false);
LuaEngine.GetInstance().CallLuaFunction(player, contentArea, "onZoneIn", true);
}
@ -1185,6 +1180,332 @@ namespace FFXIVClassic_Map_Server
}
}
public RelationGroup CreateRelationGroup(Actor inviter, Actor invitee, ulong groupType)
{
lock (groupLock)
{
groupIndexId = groupIndexId | 0x0000000000000000;
RelationGroup group = new RelationGroup(groupIndexId, inviter.actorId, invitee.actorId, 0, groupType);
mRelationGroups.Add(groupIndexId, group);
groupIndexId++;
group.SendGroupPacketsAll(inviter.actorId, invitee.actorId);
return group;
}
}
public RelationGroup GetRelationGroup(uint actorId)
{
lock (groupLock)
{
foreach (RelationGroup relation in mRelationGroups.Values)
{
if (relation.GetHost() == actorId || relation.GetOther() == actorId)
return relation;
}
return null;
}
}
public void DeleteRelationGroup(ulong groupid)
{
lock (groupLock)
{
if (mRelationGroups.ContainsKey(groupid))
mRelationGroups.Remove(groupid);
}
}
public TradeGroup CreateTradeGroup(Player inviter, Player invitee)
{
lock (groupLock)
{
groupIndexId = groupIndexId | 0x0000000000000000;
TradeGroup group = new TradeGroup(groupIndexId, inviter.actorId, invitee.actorId);
mTradeGroups.Add(groupIndexId, group);
groupIndexId++;
group.SendGroupPacketsAll(inviter.actorId, invitee.actorId);
inviter.SendGameMessage(GetActor(), 25101, 0x20, (object)invitee); //You request to trade with X
invitee.SendGameMessage(GetActor(), 25037, 0x20, (object)inviter); //X wishes to trade with you
return group;
}
}
public TradeGroup GetTradeGroup(uint actorId)
{
lock (groupLock)
{
foreach (TradeGroup group in mTradeGroups.Values)
{
if (group.GetHost() == actorId || group.GetOther() == actorId)
return (TradeGroup)group;
}
return null;
}
}
public void DeleteTradeGroup(ulong groupid)
{
lock (groupLock)
{
if (mTradeGroups.ContainsKey(groupid))
{
TradeGroup group = mTradeGroups[groupid];
group.SendDeletePackets(group.GetHost(), group.GetOther());
mTradeGroups.Remove(groupid);
}
}
}
public void TradeTEST(Player player)
{
player.KickEventSpecial(Server.GetStaticActors("TradeExecuteCommand"), 0, "commandContent", null, null, null, 16, null, null, null, null, null);
}
public void AcceptTrade(Player invitee)
{
TradeGroup group = GetTradeGroup(invitee.actorId);
if (group == null)
{
invitee.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!");
return;
}
Player inviter = (Player)invitee.GetZone().FindActorInArea(group.GetHost());
//DeleteTradeGroup(group.groupIndex);
inviter.StartTradeTransaction(invitee);
invitee.StartTradeTransaction(inviter);
inviter.KickEventSpecial(Server.GetStaticActors("TradeExecuteCommand"), 0, "commandContent", null, null, null, 16, null, null, null, null, null);
invitee.KickEventSpecial(Server.GetStaticActors("TradeExecuteCommand"), 0, "commandContent", null, null, null, 16, null, null, null, null, null);
}
public void CancelTradeTooFar(Player inviter)
{
TradeGroup group = GetTradeGroup(inviter.actorId);
if (group == null)
{
inviter.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!");
return;
}
Player invitee = (Player)inviter.GetZone().FindActorInArea(group.GetOther());
inviter.SendGameMessage(GetActor(), 25042, 0x20); //You cancel the trade.
if (invitee != null)
invitee.SendGameMessage(GetActor(), 25042, 0x20); //The trade has been canceled.
DeleteTradeGroup(group.groupIndex);
}
public void CancelTrade(Player inviter)
{
TradeGroup group = GetTradeGroup(inviter.actorId);
if (group == null)
{
inviter.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!");
return;
}
Player invitee = (Player)inviter.GetZone().FindActorInArea(group.GetOther());
inviter.SendGameMessage(GetActor(), 25041, 0x20); //You cancel the trade.
if (invitee != null)
invitee.SendGameMessage(GetActor(), 25040, 0x20); //The trade has been canceled.
DeleteTradeGroup(group.groupIndex);
}
public void RefuseTrade(Player invitee)
{
TradeGroup group = GetTradeGroup(invitee.actorId);
if (group == null)
{
invitee.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!");
return;
}
Player inviter = (Player)invitee.GetZone().FindActorInArea(group.GetHost());
if (inviter != null)
inviter.SendGameMessage(GetActor(), 25038, 0x20); //Your trade request fails
DeleteTradeGroup(group.groupIndex);
}
public void SwapTradedItems(Player p1, Player p2)
{
lock (tradeLock)
{
if (p1.IsTradeAccepted() && p2.IsTradeAccepted())
{
//move items around
p1.FinishTradeTransaction();
p2.FinishTradeTransaction();
}
}
}
public InventoryItem CreateItem(uint itemId, int amount, byte quality = 1, InventoryItem.ItemModifier modifiers = null)
{
return Database.CreateItem(itemId, amount, quality, modifiers);
}
public bool BazaarBuyOperation(Player bazaar, Player buyer, InventoryItem itemToBuy, int quantity, int cost)
{
if (bazaar == null || buyer == null || itemToBuy == null)
return false;
if (quantity <= 0)
return false;
if (cost < 0)
return false;
if (itemToBuy.GetBazaarMode() == InventoryItem.TYPE_SINGLE || itemToBuy.GetBazaarMode() == InventoryItem.TYPE_MULTI || itemToBuy.GetBazaarMode() == InventoryItem.TYPE_STACK)
{
itemToBuy.ChangeQuantity(-quantity);
buyer.AddItem(itemToBuy.itemId, quantity, itemToBuy.quality);
buyer.GetItemPackage(ItemPackage.CURRENCY_CRYSTALS).RemoveItem(1000001, cost);
}
if (itemToBuy.quantity == 0)
Database.ClearBazaarEntry(bazaar, itemToBuy);
bazaar.CheckBazaarFlags();
return true;
}
public bool BazaarSellOperation(Player bazaar, Player buyer, InventoryItem reward, int rewardQuantity, InventoryItem seek, int seekQuantity)
{
if (bazaar == null || buyer == null || reward == null || seek == null)
return false;
if (rewardQuantity <= 0 || seekQuantity <= 0)
return false;
if (reward.GetBazaarMode() == InventoryItem.TYPE_SEEK_ITEM)
{
InventoryItem seekBazaar = bazaar.GetItemPackage(ItemPackage.BAZAAR).GetItemAttachedTo(reward);
bazaar.RemoveItem(reward, rewardQuantity);
bazaar.RemoveItem(seekBazaar, seekQuantity);
bazaar.AddItem(seekBazaar);
bazaar.AddItem(seek.itemId, seekQuantity, seek.quality);
buyer.RemoveItem(seek, seekQuantity);
buyer.AddItem(reward);
}
Database.ClearBazaarEntry(bazaar, reward);
bazaar.CheckBazaarFlags();
return true;
}
public void AddToBazaar(Player player, InventoryItem reward, InventoryItem seek, int rewardAmount, int seekAmount, byte bazaarMode)
{
bool succ = false;
if (bazaarMode == InventoryItem.TYPE_SINGLE || bazaarMode == InventoryItem.TYPE_MULTI || bazaarMode == InventoryItem.TYPE_STACK)
succ = Database.CreateBazaarEntry(player, reward, seek, rewardAmount, 0, bazaarMode, seekAmount);
else
succ = Database.CreateBazaarEntry(player, reward, seek, rewardAmount, seekAmount, bazaarMode);
if (succ)
{
if (bazaarMode != InventoryItem.TYPE_SINGLE && bazaarMode != InventoryItem.TYPE_MULTI && bazaarMode != InventoryItem.TYPE_STACK)
{
reward.SetDealingAttached(bazaarMode, seek.uniqueId);
seek.SetHasAttached(true);
player.GetItemPackage(ItemPackage.BAZAAR).StartSendUpdate();
player.GetItemPackage(ItemPackage.BAZAAR).AddItem(reward);
player.GetItemPackage(ItemPackage.BAZAAR).AddItem(seek);
reward.SetAttachedIndex(ItemPackage.BAZAAR, seek.slot);
player.GetItemPackage(ItemPackage.BAZAAR).DoneSendUpdate();
}
else
{
reward.SetDealing(bazaarMode, seekAmount);
player.GetItemPackage(ItemPackage.BAZAAR).StartSendUpdate();
player.GetItemPackage(ItemPackage.BAZAAR).AddItem(reward);
player.GetItemPackage(ItemPackage.BAZAAR).DoneSendUpdate();
}
}
player.CheckBazaarFlags();
}
public void RemoveFromBazaar(Player player, InventoryItem rewardRef)
{
ushort attachedItemPackage = (ushort)((rewardRef.dealingAttached1 >> 16) & 0xFF);
ushort attachedSlot = (ushort) (rewardRef.dealingAttached1 & 0xFF);
InventoryItem seekRef = rewardRef.IsSelling() ? null : player.GetItemPackage(attachedItemPackage).GetItemAtSlot(attachedSlot);
Database.ClearBazaarEntry(player, rewardRef);
player.GetItemPackage(ItemPackage.BAZAAR).RemoveItem(rewardRef);
bool isSelling = rewardRef.IsSelling();
rewardRef.SetNormal();
if (seekRef != null)
player.GetItemPackage(ItemPackage.BAZAAR).RemoveItem(seekRef);
player.AddItem(rewardRef);
if (!isSelling)
{
seekRef.SetNormal();
player.AddItem(seekRef);
}
player.CheckBazaarFlags();
}
/*
public void TransactionBazaar(Player owner, Player other, InventoryItem reward, InventoryItem seek, int rewardAmount, int seekAmount)
{
Database.ClearBazaarEntry(owner, reward, seek);
//Remove Bazaar Items from owner
owner.GetInventory(Inventory.BAZAAR).RemoveItem(reward);
owner.GetInventory(Inventory.BAZAAR).RemoveItem(seek);
//Remove Seek item from other
if (seek.GetItemData().IsMoney())
other.GetInventory(Inventory.CURRENCY_CRYSTALS).RemoveItem(seek.itemId, seekAmount);
else
other.GetInventory(Inventory.NORMAL).RemoveItem(seek.itemId, seekAmount);
//Add reward to other, seek to owner
if (reward.GetItemData().IsMoney())
other.GetInventory(Inventory.CURRENCY_CRYSTALS).AddItem(reward.itemId, rewardAmount);
else
other.GetInventory(Inventory.NORMAL).AddItem(reward);
if (seek.GetItemData().IsMoney())
owner.GetInventory(Inventory.CURRENCY_CRYSTALS).AddItem(seek.itemId, seekAmount);
else
other.GetInventory(Inventory.NORMAL).AddItem(seek);
}*/
public bool SendGroupInit(Session session, ulong groupId)
{
if (mContentGroups.ContainsKey(groupId))
@ -1192,6 +1513,11 @@ namespace FFXIVClassic_Map_Server
mContentGroups[groupId].SendInitWorkValues(session);
return true;
}
else if (mTradeGroups.ContainsKey(groupId))
{
mTradeGroups[groupId].SendInitWorkValues(session);
return true;
}
return false;
}

View file

@ -1,5 +1,4 @@
using FFXIVClassic_Map_Server;
using FFXIVClassic.Common;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.lua;

View file

@ -3,11 +3,7 @@ using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
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.area
{

View file

@ -1,12 +1,7 @@
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.area
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.area
namespace FFXIVClassic_Map_Server.actors.area
{
class SpawnLocation
{

View file

@ -1,7 +1,4 @@
using FFXIVClassic_Map_Server;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
@ -11,7 +8,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using FFXIVClassic_Map_Server.actors.director;
namespace FFXIVClassic_Map_Server.actors.area

View file

@ -1,9 +1,12 @@

using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.player;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.utils;
using FFXIVClassic_Map_Server.actors.chara.ai;
using System;
@ -132,7 +135,12 @@ namespace FFXIVClassic_Map_Server.Actors
protected Dictionary<string, UInt64> tempVars = new Dictionary<string, UInt64>();
public Character(uint actorID) : base(actorID)
//Inventory
protected Dictionary<ushort, ItemPackage> itemPackages = new Dictionary<ushort, ItemPackage>();
protected Equipment equipment;
public Character(uint actorID)
: base(actorID)
{
//Init timer array to "notimer"
for (int i = 0; i < charaWork.statusShownTime.Length; i++)
@ -1133,5 +1141,180 @@ namespace FFXIVClassic_Map_Server.Actors
targetFind.FindWithinArea(this, ValidTarget.PartyMember, TargetFindAOETarget.Self);
return targetFind.GetTargets();
}
#region Inventory
public void SendItemPackage(Player player, uint id)
{
if (!itemPackages.ContainsKey((ushort)id))
return;
player.QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true));
itemPackages[(ushort)id].SendFullInventory(player);
player.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
}
public void AddItem(uint catalogID)
{
AddItem(catalogID, 1);
}
public void AddItem(uint catalogID, int quantity)
{
AddItem(catalogID, quantity, 1);
}
public void AddItem(uint catalogID, int quantity, byte quality)
{
ushort itemPackage = GetPackageForItem(catalogID);
if (itemPackages.ContainsKey(itemPackage))
{
itemPackages[itemPackage].AddItem(catalogID, quantity, quality);
}
}
public void AddItem(InventoryItem item)
{
ushort itemPackage = GetPackageForItem(item.GetItemData().catalogID);
if (itemPackages.ContainsKey(itemPackage))
{
itemPackages[itemPackage].AddItem(item);
}
}
public void SetItem(InventoryItem item, ushort itemPackage, ushort slot)
{
if (itemPackages.ContainsKey(itemPackage))
{
itemPackages[itemPackage].SetItem(slot, item);
}
}
public void MoveItem(InventoryItem item, ushort destinationPackage)
{
ushort sourcePackage = item.itemPackage;
if (!itemPackages.ContainsKey(sourcePackage) && !itemPackages.ContainsKey(destinationPackage))
return;
itemPackages[sourcePackage].RemoveItem(item);
itemPackages[destinationPackage].AddItem(item);
}
public void RemoveItem(uint catalogID)
{
RemoveItem(catalogID, 1);
}
public void RemoveItem(uint catalogID, int quantity)
{
RemoveItem(catalogID, quantity, 1);
}
public void RemoveItem(uint catalogID, int quantity, byte quality)
{
ushort itemPackage = GetPackageForItem(catalogID);
if (itemPackages.ContainsKey(itemPackage))
{
itemPackages[itemPackage].RemoveItem(catalogID, quantity, quality);
}
}
public void RemoveItemAtSlot(ushort itemPackage, ushort slot)
{
if (itemPackages.ContainsKey(itemPackage))
{
itemPackages[itemPackage].RemoveItemAtSlot(slot);
}
}
public void RemoveItem(InventoryItem item)
{
RemoveItem(item, 1);
}
public void RemoveItem(InventoryItem item, int quantity)
{
if (itemPackages.ContainsKey(item.itemPackage))
{
itemPackages[item.itemPackage].RemoveItem(item, quantity);
}
}
public bool HasItem(uint catalogID)
{
return HasItem(catalogID, 1);
}
public bool HasItem(uint catalogID, int minQuantity)
{
return HasItem(catalogID, minQuantity, 1);
}
public bool HasItem(uint catalogID, int minQuantity, byte quality)
{
ushort itemPackage = GetPackageForItem(catalogID);
if (itemPackages.ContainsKey(itemPackage))
{
return itemPackages[itemPackage].HasItem(catalogID, minQuantity, quality);
}
return false;
}
public bool HasItem(InventoryItem item)
{
ushort itemPackage = GetPackageForItem(item.GetItemData().catalogID);
if (itemPackages.ContainsKey(itemPackage))
{
//return itemPackages[itemPackage].HasItem(item);
return false; //TODO FIX
}
else
return false;
}
public InventoryItem GetItem(LuaUtils.ItemRefParam reference)
{
if (reference.actorId != actorId)
return null;
if (itemPackages.ContainsKey(reference.itemPackage))
{
return itemPackages[reference.itemPackage].GetItemAtSlot(reference.slot);
}
return null;
}
public ItemPackage GetItemPackage(ushort package)
{
if (itemPackages.ContainsKey(package))
return itemPackages[package];
else
return null;
}
public ushort GetPackageForItem(uint catalogID)
{
ItemData data = Server.GetItemGamedata(catalogID);
if (data == null)
return ItemPackage.NORMAL;
else
{
if (data.IsMoney())
return ItemPackage.CURRENCY_CRYSTALS;
else if (data.IsImportant())
return ItemPackage.KEYITEMS;
else
return ItemPackage.NORMAL;
}
}
//public void removeItem(byUniqueId)
//public void removeItem(byUniqueId, quantity)
//public void removeItem(slot)
//public void removeItem(slot, quantity)
#endregion
}
}

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.chara.npc
namespace FFXIVClassic_Map_Server.actors.chara.npc
{
class ActorClass
{

View file

@ -1,14 +1,10 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.utils;
using MoonSharp.Interpreter;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using System;

View file

@ -1,12 +1,6 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.chara.player;
using FFXIVClassic_Map_Server.actors.chara.player;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.chara.npc
{
@ -18,7 +12,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.npc
private uint retainerId;
private Player ownerPlayer;
private Dictionary<ushort, Inventory> inventories = new Dictionary<ushort, Inventory>();
public Retainer(uint retainerId, ActorClass actorClass, Player player, float posX, float posY, float posZ, float rot)
: base(0, actorClass, "myretainer", player.GetZone(), posX, posY, posZ, rot, 0, 0, null)
@ -27,33 +20,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.npc
this.ownerPlayer = player;
this.actorName = String.Format("_rtnre{0:x7}", actorId);
inventories[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL);
inventories[Inventory.CURRENCY_CRYSTALS] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRENCY_CRYSTALS);
inventories[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR);
itemPackages[ItemPackage.NORMAL] = new ItemPackage(this, MAXSIZE_INVENTORY_NORMAL, ItemPackage.NORMAL);
itemPackages[ItemPackage.CURRENCY_CRYSTALS] = new ItemPackage(this, MAXSIZE_INVENTORY_CURRANCY, ItemPackage.CURRENCY_CRYSTALS);
itemPackages[ItemPackage.BAZAAR] = new ItemPackage(this, MAXSIZE_INVENTORY_BAZAAR, ItemPackage.BAZAAR);
inventories[Inventory.NORMAL].InitList(Database.GetInventory(this, Inventory.NORMAL));
inventories[Inventory.CURRENCY_CRYSTALS].InitList(Database.GetInventory(this, Inventory.CURRENCY_CRYSTALS));
inventories[Inventory.BAZAAR].InitList(Database.GetInventory(this, Inventory.BAZAAR));
itemPackages[ItemPackage.NORMAL].InitList(Database.GetInventory(this, ItemPackage.NORMAL));
itemPackages[ItemPackage.CURRENCY_CRYSTALS].InitList(Database.GetInventory(this, ItemPackage.CURRENCY_CRYSTALS));
itemPackages[ItemPackage.BAZAAR].InitList(Database.GetInventory(this, ItemPackage.BAZAAR));
}
public Inventory GetInventory(ushort type)
{
if (inventories.ContainsKey(type))
return inventories[type];
else
return null;
}
public void SendFullRetainerInventory(Player player)
{
player.QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId));
inventories[Inventory.NORMAL].SendFullInventory(player);
inventories[Inventory.CURRENCY_CRYSTALS].SendFullInventory(player);
inventories[Inventory.BAZAAR].SendFullInventory(player);
player.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
}
public uint getRetainerId()
public uint GetRetainerId()
{
return retainerId;
}

View file

@ -30,11 +30,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
private ushort inventoryCapacity;
private ushort inventoryCode;
private InventoryItem[] list;
private Inventory normalInventory;
private ItemPackage normalInventory;
private bool writeToDB = true;
public Equipment(Player ownerPlayer, Inventory normalInventory, ushort capacity, ushort code)
public Equipment(Player ownerPlayer, ItemPackage normalInventory, ushort capacity, ushort code)
{
owner = ownerPlayer;
inventoryCapacity = capacity;
@ -63,7 +63,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
}
}
toPlayer.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, 0x23, Inventory.EQUIPMENT_OTHERPLAYER));
toPlayer.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, 0x23, ItemPackage.EQUIPMENT_OTHERPLAYER));
int currentIndex = 0;
while (true)

View file

@ -10,16 +10,17 @@ using System.Linq;
namespace FFXIVClassic_Map_Server.actors.chara.player
{
class Inventory
class ItemPackage
{
public const ushort NORMAL = 0; //Max 0xC8
public const ushort TRADE = 1; //Max 0x96
public const ushort UNKNOWN = 1; //Max 0x96
public const ushort LOOT = 4; //Max 0xA
public const ushort MELDREQUEST = 5; //Max 0x04
public const ushort BAZAAR = 7; //Max 0x0A
public const ushort CURRENCY_CRYSTALS = 99; //Max 0x140
public const ushort KEYITEMS = 100; //Max 0x500
public const ushort EQUIPMENT = 0x00FE; //Max 0x23
public const ushort TRADE = 0x00FD; //Max 0x04
public const ushort EQUIPMENT_OTHERPLAYER = 0x00F9; //Max 0x23
public enum INV_ERROR {
@ -30,19 +31,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
};
private Character owner;
private ushort inventoryCapacity;
private ushort inventoryCode;
private ushort itemPackageCapacity;
private ushort itemPackageCode;
private bool isTemporary;
private InventoryItem[] list;
private bool[] isDirty;
private bool holdingUpdates = false;
private int endOfListIndex = 0;
public Inventory(Character ownerPlayer, ushort capacity, ushort code, bool temporary = false)
public ItemPackage(Character ownerPlayer, ushort capacity, ushort code, bool temporary = false)
{
owner = ownerPlayer;
inventoryCapacity = capacity;
inventoryCode = code;
itemPackageCapacity = capacity;
itemPackageCode = code;
isTemporary = temporary;
list = new InventoryItem[capacity];
isDirty = new bool[capacity];
@ -53,7 +55,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
{
int i = 0;
foreach (InventoryItem item in itemsFromDB)
{
item.RefreshPositioning(owner, itemPackageCode, (ushort) i);
list[i++] = item;
}
endOfListIndex = i;
}
@ -93,56 +98,73 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
return null;
}
public int GetItemQuantity(uint itemId)
public InventoryItem GetItemAttachedTo(InventoryItem attachedTo)
{
return GetItemQuantity(itemId, 1);
}
public int GetItemQuantity(uint itemId, uint quality)
{
int count = 0;
for (int i = endOfListIndex - 1; i >= 0; i--)
for (int i = 0; i < endOfListIndex; i++)
{
InventoryItem item = list[i];
if (item.itemId == itemId && item.quality == quality)
count += item.quantity;
Debug.Assert(item != null, "Item slot was null!!!");
if (attachedTo.GetAttached() == item.uniqueId)
return item;
}
return null;
}
return count;
}
public int AddItem(uint itemId)
public INV_ERROR AddItem(uint itemId)
{
return AddItem(itemId, 1, 1);
}
public void AddItem(uint[] itemId)
{
for (int i = 0; i < itemId.Length; i++)
AddItem(itemId[i]);
}
public int AddItem(uint itemId, int quantity)
public INV_ERROR AddItem(uint itemId, int quantity)
{
return AddItem(itemId, quantity, 1);
}
public int AddItem(uint itemId, int quantity, byte quality)
public INV_ERROR AddItem(InventoryItem itemRef)
{
//If it isn't a single item (ie: armor) just add like normal (not valid for BAZAAR)
if (itemPackageCode != BAZAAR && itemRef.GetItemData().maxStack > 1)
return AddItem(itemRef.itemId, itemRef.quantity, itemRef.quality);
if (!IsSpaceForAdd(itemRef.itemId, itemRef.quantity, itemRef.quality))
return INV_ERROR.INVENTORY_FULL;
ItemData gItem = Server.GetItemGamedata(itemRef.itemId);
if (gItem == null)
{
Program.Log.Error("Inventory.AddItem: unable to find item %u", itemRef.itemId);
return INV_ERROR.SYSTEM_ERROR;
}
itemRef.RefreshPositioning(owner, itemPackageCode, (ushort)endOfListIndex);
isDirty[endOfListIndex] = true;
list[endOfListIndex++] = itemRef;
DoDatabaseAdd(itemRef);
SendUpdatePackets();
return INV_ERROR.SUCCESS;
}
public INV_ERROR AddItem(uint itemId, int quantity, byte quality)
{
if (!IsSpaceForAdd(itemId, quantity, quality))
return (int)INV_ERROR.INVENTORY_FULL;
return INV_ERROR.INVENTORY_FULL;
ItemData gItem = Server.GetItemGamedata(itemId);
//If it's unique, abort
if (HasItem(itemId) && gItem.isExclusive)
return INV_ERROR.ALREADY_HAS_UNIQUE;
if (gItem == null)
{
Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId);
return (int)INV_ERROR.SYSTEM_ERROR;
return INV_ERROR.SYSTEM_ERROR;
}
//Check if item id exists
@ -167,15 +189,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
}
}
//If it's unique, abort
if (HasItem(itemId) && gItem.isRare)
return (int)INV_ERROR.ALREADY_HAS_UNIQUE;
//New item that spilled over
while (quantityCount > 0)
{
InventoryItem addedItem = Database.CreateItem(itemId, Math.Min(quantityCount, gItem.maxStack), quality, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability);
addedItem.slot = (ushort)endOfListIndex;
InventoryItem.ItemModifier modifiers = null;
if (gItem.durability != 0)
{
modifiers = new InventoryItem.ItemModifier();
modifiers.durability = (uint)gItem.durability;
}
InventoryItem addedItem = Database.CreateItem(itemId, Math.Min(quantityCount, gItem.maxStack), quality, modifiers);
addedItem.RefreshPositioning(owner, itemPackageCode, (ushort)endOfListIndex);
isDirty[endOfListIndex] = true;
list[endOfListIndex++] = addedItem;
quantityCount -= gItem.maxStack;
@ -185,7 +210,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
SendUpdatePackets();
return (int)INV_ERROR.SUCCESS;
return INV_ERROR.SUCCESS;
}
public void SetItem(ushort slot, InventoryItem item)
{
list[slot] = item;
SendUpdatePackets();
item.RefreshPositioning(owner, itemPackageCode, slot);
}
public void RemoveItem(uint itemId)
@ -230,8 +262,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
else
{
item.quantity -= quantityCount;
DoDatabaseQuantity(list[i].uniqueId, list[i].quantity);
}
DoDatabaseQuantity(list[i].uniqueId, list[i].quantity);}
isDirty[i] = true;
@ -247,11 +278,21 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
SendUpdatePackets();
}
public void RemoveItemByUniqueId(ulong itemDBId)
public void RemoveItem(InventoryItem item)
{
RemoveItemByUniqueId(item.uniqueId, item.quantity);
}
public void RemoveItem(InventoryItem item, int quantity)
{
RemoveItemByUniqueId(item.uniqueId, quantity);
}
public void RemoveItemByUniqueId(ulong itemDBId, int quantity)
{
ushort slot = 0;
InventoryItem toDelete = null;
for (int i = endOfListIndex - 1; i >= 0; i--)
for (int i = 0; i < endOfListIndex; i++)
{
InventoryItem item = list[i];
@ -268,9 +309,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
if (toDelete == null)
return;
if (quantity >= toDelete.quantity)
{
DoDatabaseRemove(toDelete.uniqueId);
list[slot].RefreshPositioning(null, 0xFFFF, 0xFFFF);
list[slot] = null;
}
else
{
list[slot].quantity -= quantity;
DoDatabaseQuantity(list[slot].uniqueId, list[slot].quantity);
}
isDirty[slot] = true;
DoRealign();
@ -284,6 +334,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
DoDatabaseRemove(list[slot].uniqueId);
list[slot].RefreshPositioning(null, 0xFFFF, 0xFFFF);
list[slot] = null;
isDirty[slot] = true;
@ -304,6 +355,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
{
DoDatabaseRemove(list[slot].uniqueId);
list[slot].RefreshPositioning(null, 0xFFFF, 0xFFFF);
list[slot] = null;
DoRealign();
}
@ -315,6 +367,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
}
}
public void Clear()
{
for (int i = 0; i < endOfListIndex; i++)
{
list[i].RefreshPositioning(null, 0xFFFF, 0xFFFF);
list[i] = null;
isDirty[i] = true;
}
endOfListIndex = 0;
SendUpdatePackets();
}
public InventoryItem[] GetRawList()
{
return list;
}
public void ChangeDurability(uint slot, uint durabilityChange)
{
isDirty[slot] = true;
@ -334,7 +404,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
#region Packet Functions
public void SendFullInventory(Player player)
{
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode));
SendInventoryPackets(player, 0);
player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
@ -366,7 +436,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
else
break;
}
}
private void SendInventoryPackets(Player player, int startOffset)
@ -395,7 +464,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
else
break;
}
}
private void SendInventoryRemovePackets(Player player, ushort index)
@ -425,26 +493,25 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
else
break;
}
}
public void RefreshItem(Player player, InventoryItem item)
{
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode));
SendInventoryPackets(player, item);
player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
public void RefreshItem(Player player, params InventoryItem[] items)
{
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode));
SendInventoryPackets(player, items.ToList());
player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
public void RefreshItem(Player player, List<InventoryItem> items)
{
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode));
SendInventoryPackets(player, items);
player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
@ -458,10 +525,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
if (isTemporary)
return;
if (itemPackageCode == BAZAAR)
return;
if (owner is Player)
Database.AddItem((Player)owner, addedItem, inventoryCode);
Database.AddItem((Player)owner, addedItem, itemPackageCode);
else if (owner is Retainer)
Database.AddItem((Retainer)owner, addedItem, inventoryCode);
Database.AddItem((Retainer)owner, addedItem, itemPackageCode);
}
private void DoDatabaseQuantity(ulong itemDBId, int quantity)
@ -469,10 +539,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
if (isTemporary)
return;
if (owner is Player)
Database.SetQuantity((Player)owner, itemDBId, inventoryCode);
else if (owner is Retainer)
Database.SetQuantity((Retainer)owner, itemDBId, inventoryCode);
if (itemPackageCode == BAZAAR)
return;
Database.SetQuantity(itemDBId, quantity);
}
private void DoDatabaseRemove(ulong itemDBId)
@ -480,6 +551,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
if (isTemporary)
return;
if (itemPackageCode == BAZAAR)
return;
if (owner is Player)
Database.RemoveItem((Player)owner, itemDBId);
else if (owner is Retainer)
@ -488,13 +562,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
private void SendUpdatePackets()
{
if (owner is Player)
if (owner is Player && !holdingUpdates)
{
SendUpdatePackets((Player)owner, true);
SendUpdatePackets((Player)owner);
}
}
public void SendUpdatePackets(Player player, bool doneImmediate = false)
public void SendUpdatePackets(Player player)
{
List<InventoryItem> items = new List<InventoryItem>();
List<ushort> slotsToRemove = new List<ushort>();
@ -513,11 +587,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
slotsToRemove.Add((ushort)i);
}
if (doneImmediate)
DoneSendUpdate();
if (!holdingUpdates)
Array.Clear(isDirty, 0, isDirty.Length);
player.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode));
//Send Updated Slots
SendInventoryPackets(player, items);
//Send Remove packets for tail end
@ -526,8 +600,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
player.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
}
public void StartSendUpdate()
{
holdingUpdates = true;
}
public void DoneSendUpdate()
{
holdingUpdates = false;
SendUpdatePackets();
Array.Clear(isDirty, 0, isDirty.Length);
}
@ -537,7 +618,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
public bool IsFull()
{
return endOfListIndex >= inventoryCapacity;
return endOfListIndex >= itemPackageCapacity;
}
public bool IsSpaceForAdd(uint itemId, int quantity, int quality)
@ -621,5 +702,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
#endregion
public int GetCount()
{
return endOfListIndex;
}
}
}

View file

@ -23,6 +23,9 @@ using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.packets.send.player;
using FFXIVClassic_Map_Server.packets.send.actor.battle;
using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group;
using FFXIVClassic_Map_Server.actors.chara.npc;
namespace FFXIVClassic_Map_Server.Actors
{
@ -71,7 +74,6 @@ namespace FFXIVClassic_Map_Server.Actors
//Event Related
public uint currentEventOwner = 0;
public string currentEventName = "";
public Coroutine currentEventRunning;
//Player Info
@ -84,9 +86,11 @@ namespace FFXIVClassic_Map_Server.Actors
public bool isGM = false;
public bool isZoneChanging = true;
//Inventory
private Dictionary<ushort, Inventory> inventories = new Dictionary<ushort, Inventory>();
private Equipment equipment;
//Trading
private Player otherTrader = null;
private ItemPackage myOfferings;
private bool isTradeAccepted = false;
private bool isTradeLocked = false;
//GC Related
public byte gcCurrent;
@ -115,6 +119,10 @@ namespace FFXIVClassic_Map_Server.Actors
public uint homepoint = 0;
public byte homepointInn = 0;
//Nameplate Stuff
public uint currentLSPlate = 0;
public byte repairType = 0;
//Retainer
RetainerMeetingRelationGroup retainerMeetingGroup = null;
public Retainer currentSpawnedRetainer = null;
@ -138,14 +146,14 @@ namespace FFXIVClassic_Map_Server.Actors
moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN;
moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_ACTIVE;
inventories[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL);
inventories[Inventory.KEYITEMS] = new Inventory(this, MAXSIZE_INVENTORY_KEYITEMS, Inventory.KEYITEMS);
inventories[Inventory.CURRENCY_CRYSTALS] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRENCY_CRYSTALS);
inventories[Inventory.MELDREQUEST] = new Inventory(this, MAXSIZE_INVENTORY_MELDREQUEST, Inventory.MELDREQUEST);
inventories[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR);
inventories[Inventory.LOOT] = new Inventory(this, MAXSIZE_INVENTORY_LOOT, Inventory.LOOT);
itemPackages[ItemPackage.NORMAL] = new ItemPackage(this, MAXSIZE_INVENTORY_NORMAL, ItemPackage.NORMAL);
itemPackages[ItemPackage.KEYITEMS] = new ItemPackage(this, MAXSIZE_INVENTORY_KEYITEMS, ItemPackage.KEYITEMS);
itemPackages[ItemPackage.CURRENCY_CRYSTALS] = new ItemPackage(this, MAXSIZE_INVENTORY_CURRANCY, ItemPackage.CURRENCY_CRYSTALS);
itemPackages[ItemPackage.MELDREQUEST] = new ItemPackage(this, MAXSIZE_INVENTORY_MELDREQUEST, ItemPackage.MELDREQUEST);
itemPackages[ItemPackage.BAZAAR] = new ItemPackage(this, MAXSIZE_INVENTORY_BAZAAR, ItemPackage.BAZAAR);
itemPackages[ItemPackage.LOOT] = new ItemPackage(this, MAXSIZE_INVENTORY_LOOT, ItemPackage.LOOT);
equipment = new Equipment(this, inventories[Inventory.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, Inventory.EQUIPMENT);
equipment = new Equipment(this, itemPackages[ItemPackage.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, ItemPackage.EQUIPMENT);
//Set the Skill level caps of all FFXIV (classes)skills to 50
for (int i = 0; i < charaWork.battleSave.skillLevelCap.Length; i++)
@ -474,6 +482,17 @@ namespace FFXIVClassic_Map_Server.Actors
propPacketUtil.AddProperty(String.Format("work.guildleveChecked[{0}]", i));
}
//Bazaar
CheckBazaarFlags(true);
if (charaWork.eventSave.repairType != 0)
propPacketUtil.AddProperty("charaWork.eventSave.repairType");
if (charaWork.eventTemp.bazaarRetail)
propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRetail");
if (charaWork.eventTemp.bazaarRepair)
propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRepair");
if (charaWork.eventTemp.bazaarMateria)
propPacketUtil.AddProperty("charaWork.eventTemp.bazaarMateria");
//NPC Linkshell
for (int i = 0; i < playerWork.npcLinkshellChatCalling.Length; i++)
{
@ -514,13 +533,13 @@ namespace FFXIVClassic_Map_Server.Actors
//GetSpawnPackets(actorId, spawnType).DebugPrintPacket();
#region Inventory & Equipment
QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId));
inventories[Inventory.NORMAL].SendFullInventory(this);
inventories[Inventory.CURRENCY_CRYSTALS].SendFullInventory(this);
inventories[Inventory.KEYITEMS].SendFullInventory(this);
inventories[Inventory.BAZAAR].SendFullInventory(this);
inventories[Inventory.MELDREQUEST].SendFullInventory(this);
inventories[Inventory.LOOT].SendFullInventory(this);
QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true));
itemPackages[ItemPackage.NORMAL].SendFullInventory(this);
itemPackages[ItemPackage.CURRENCY_CRYSTALS].SendFullInventory(this);
itemPackages[ItemPackage.KEYITEMS].SendFullInventory(this);
itemPackages[ItemPackage.BAZAAR].SendFullInventory(this);
itemPackages[ItemPackage.MELDREQUEST].SendFullInventory(this);
itemPackages[ItemPackage.LOOT].SendFullInventory(this);
equipment.SendFullEquipment(false);
playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
#endregion
@ -623,6 +642,33 @@ namespace FFXIVClassic_Map_Server.Actors
}
}
public void BroadcastPackets(List<SubPacket> packets, bool sendToSelf)
{
foreach (SubPacket packet in packets)
{
if (sendToSelf)
{
SubPacket clonedPacket = new SubPacket(packet, actorId);
QueuePacket(clonedPacket);
}
foreach (Actor a in playerSession.actorInstanceList)
{
if (a is Player)
{
Player p = (Player)a;
if (p.Equals(this))
continue;
SubPacket clonedPacket = new SubPacket(packet, a.actorId);
p.QueuePacket(clonedPacket);
}
}
}
}
public void BroadcastPacket(SubPacket packet, bool sendToSelf)
{
if (sendToSelf)
@ -937,6 +983,8 @@ namespace FFXIVClassic_Map_Server.Actors
public void PrepareClassChange(byte classId)
{
//If new class, init abilties and level
if (charaWork.battleSave.skillLevel[classId - 1] <= 0)
UpdateClassLevel(classId, 1);
SendCharaExpInfo();
}
@ -1003,6 +1051,16 @@ namespace FFXIVClassic_Map_Server.Actors
RecalculateStats();
}
public void UpdateClassLevel(byte classId, short level)
{
Database.PlayerCharacterUpdateClassLevel(this, classId, level);
charaWork.battleSave.skillLevel[classId - 1] = level;
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/exp", this);
propertyBuilder.AddProperty(String.Format("charaWork.battleSave.skillLevel[{0}]", classId-1));
List<SubPacket> packets = propertyBuilder.Done();
QueuePackets(packets);
}
public void GraphicChange(int slot, InventoryItem invItem)
{
if (invItem == null)
@ -1048,18 +1106,68 @@ namespace FFXIVClassic_Map_Server.Actors
BroadcastPacket(CreateAppearancePacket(), true);
}
public Inventory GetInventory(ushort type)
public void SetRepairRequest(byte type)
{
if (inventories.ContainsKey(type))
return inventories[type];
else
return null;
charaWork.eventSave.repairType = type;
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/bazaar", this);
propPacketUtil.AddProperty("charaWork.eventSave.repairType");
QueuePackets(propPacketUtil.Done());
}
public void CheckBazaarFlags(bool noUpdate = false)
{
bool isDealing = false, isRepairing = false, seekingItem = false;
lock (GetItemPackage(ItemPackage.BAZAAR))
{
foreach (InventoryItem item in GetItemPackage(ItemPackage.BAZAAR).GetRawList())
{
if (item == null)
break;
if (item.GetBazaarMode() == InventoryItem.TYPE_SINGLE || item.GetBazaarMode() == InventoryItem.TYPE_MULTI || item.GetBazaarMode() == InventoryItem.TYPE_STACK)
isDealing = true;
if (item.GetBazaarMode() == InventoryItem.TYPE_SEEK_REPAIR)
isRepairing = true;
if (item.GetBazaarMode() == InventoryItem.TYPE_SEEK_ITEM)
isDealing = true;
if (isDealing && isRepairing && seekingItem)
break;
}
}
bool doUpdate = false;
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/bazaar", this);
if (charaWork.eventTemp.bazaarRetail != isDealing)
{
charaWork.eventTemp.bazaarRetail = isDealing;
propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRetail");
doUpdate = true;
}
if (charaWork.eventTemp.bazaarRepair != isRepairing)
{
charaWork.eventTemp.bazaarRepair = isRepairing;
propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRepair");
doUpdate = true;
}
if (charaWork.eventTemp.bazaarMateria != (GetItemPackage(ItemPackage.MELDREQUEST).GetCount() != 0))
{
charaWork.eventTemp.bazaarMateria = GetItemPackage(ItemPackage.MELDREQUEST).GetCount() != 0;
propPacketUtil.AddProperty("charaWork.eventTemp.bazaarMateria");
doUpdate = true;
}
if (!noUpdate && doUpdate)
BroadcastPackets(propPacketUtil.Done(), true);
}
public int GetCurrentGil()
{
if (GetInventory(Inventory.CURRENCY_CRYSTALS).HasItem(1000001))
return GetInventory(Inventory.CURRENCY_CRYSTALS).GetItemByCatelogId(1000001).quantity;
if (HasItem(1000001))
return GetItemPackage(ItemPackage.CURRENCY_CRYSTALS).GetItemByCatelogId(1000001).quantity;
else
return 0;
}
@ -1576,8 +1684,10 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendMyTradeToPlayer(Player player)
{
Inventory tradeInventory = new Inventory(this, 4, Inventory.TRADE);
ItemPackage tradeInventory = new ItemPackage(this, 4, ItemPackage.TRADE);
player.QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true));
tradeInventory.SendFullInventory(player);
player.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
}
public void SendDataPacket(params object[] parameters)
@ -1590,6 +1700,8 @@ namespace FFXIVClassic_Map_Server.Actors
public void StartEvent(Actor owner, EventStartPacket start)
{
currentEventOwner = start.scriptOwnerActorID;
currentEventName = start.triggerName;
LuaEngine.GetInstance().EventStarted(this, owner, start);
}
@ -1604,7 +1716,18 @@ namespace FFXIVClassic_Map_Server.Actors
return;
List<LuaParam> lParams = LuaUtils.CreateLuaParamList(parameters);
SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, conditionName, lParams);
SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, 0x75dc1705, conditionName, lParams);
spacket.DebugPrintSubPacket();
QueuePacket(spacket);
}
public void KickEventSpecial(Actor actor, uint unknown, string conditionName, params object[] parameters)
{
if (actor == null)
return;
List<LuaParam> lParams = LuaUtils.CreateLuaParamList(parameters);
SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, unknown, conditionName, lParams);
spacket.DebugPrintSubPacket();
QueuePacket(spacket);
}
@ -2572,5 +2695,127 @@ namespace FFXIVClassic_Map_Server.Actors
return equippedItem != null && equippedItem.itemId == itemId;
}
public Retainer GetSpawnedRetainer()
{
return currentSpawnedRetainer;
}
public void StartTradeTransaction(Player otherPlayer)
{
myOfferings = new ItemPackage(this, 4, ItemPackage.TRADE, true);
ItemPackage otherPlayerOfferings = new ItemPackage(otherPlayer, 4, ItemPackage.TRADE, true);
myOfferings.StartSendUpdate();
myOfferings.SendUpdatePackets(this);
myOfferings.SendUpdatePackets(otherPlayer);
myOfferings.DoneSendUpdate();
otherTrader = otherPlayer;
isTradeAccepted = false;
}
public Player GetOtherTrader()
{
return otherTrader;
}
public ItemPackage GetTradeOfferings()
{
return myOfferings;
}
public bool IsTrading()
{
return otherTrader != null;
}
public bool IsTradeAccepted()
{
return isTradeAccepted;
}
public void AddTradeItem(ushort slot, ushort linkedSlot, int subquantity)
{
if (!IsTrading())
return;
InventoryItem mine = itemPackages[ItemPackage.NORMAL].GetItemAtSlot(linkedSlot);
InventoryItem tradeItem = new InventoryItem(mine, slot);
myOfferings.StartSendUpdate();
myOfferings.AddItem(mine.itemId, mine.quantity, mine.quality);
myOfferings.SendUpdatePackets(otherTrader);
myOfferings.DoneSendUpdate();
}
public void AddTradeGil(int quantity)
{
if (!IsTrading())
return;
myOfferings.StartSendUpdate();
myOfferings.AddItem(1000001, quantity, 1);
myOfferings.SendUpdatePackets(otherTrader);
myOfferings.DoneSendUpdate();
}
public void RemoveTradeItem(ushort slot)
{
if (!IsTrading())
return;
myOfferings.StartSendUpdate();
myOfferings.RemoveItemAtSlot(slot);
myOfferings.SendUpdatePackets(otherTrader);
myOfferings.DoneSendUpdate();
}
public void ClearTradeItems(ushort slot)
{
if (!IsTrading())
return;
myOfferings.StartSendUpdate();
myOfferings.Clear();
myOfferings.SendUpdatePackets(otherTrader);
myOfferings.DoneSendUpdate();
}
public void AcceptTrade(bool accepted)
{
if (!IsTrading())
return;
isTradeAccepted = accepted;
}
public void FinishTradeTransaction()
{
isTradeAccepted = false;
myOfferings = null;
otherTrader = null;
}
public void Test()
{
QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId));
QueuePacket(InventorySetBeginPacket.BuildPacket(actorId, 4, ItemPackage.TRADE));
QueuePacket(InventoryRemoveX01Packet.BuildPacket(actorId, 1));
QueuePacket(InventorySetEndPacket.BuildPacket(actorId));
QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
}
public void Test2()
{
QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId));
QueuePacket(InventorySetBeginPacket.BuildPacket(actorId, 4, ItemPackage.TRADE));
QueuePacket(EquipmentListX01Packet.BuildPacket(actorId, 1, 1));
QueuePacket(InventorySetEndPacket.BuildPacket(actorId));
QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
}
}
}

View file

@ -8,7 +8,6 @@ using FFXIVClassic_Map_Server.packets.send.actor;
using MoonSharp.Interpreter;
using System;
using System.Collections.Generic;
using System.IO;
namespace FFXIVClassic_Map_Server.actors.director
{

View file

@ -1,15 +1,10 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.director.Work;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.director
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.director.Work
namespace FFXIVClassic_Map_Server.actors.director.Work
{
class GuildleveWork

View file

@ -5,12 +5,7 @@ using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using FFXIVClassic_Map_Server.utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group
{

View file

@ -1,16 +1,4 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.actors.group.Work;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using FFXIVClassic_Map_Server.utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Map_Server.actors.director;
namespace FFXIVClassic_Map_Server.actors.group
{

View file

@ -2,7 +2,6 @@
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using System;
using System.Collections.Generic;
namespace FFXIVClassic_Map_Server.actors.group

View file

@ -2,11 +2,7 @@
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group
{

View file

@ -1,12 +1,6 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group.Work;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.actors.group.Work;
using FFXIVClassic_Map_Server.packets.send.group;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group
{

View file

@ -3,21 +3,17 @@ using FFXIVClassic_Map_Server.actors.group.Work;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group
{
class Relation : Group
class RelationGroup : Group
{
public RelationWork work = new RelationWork();
private uint charaOther;
private ulong topicGroup;
public Relation(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex)
public RelationGroup(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex)
{
this.charaOther = other;
work._globalTemp.host = ((ulong)host << 32) | (0xc17909);

View file

@ -4,11 +4,7 @@ using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group
{

View file

@ -0,0 +1,73 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group.Work;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using System.Collections.Generic;
namespace FFXIVClassic_Map_Server.actors.group
{
class TradeGroup : Group
{
public RelationWork work = new RelationWork();
private uint charaOther;
private ulong topicGroup;
public TradeGroup(ulong groupIndex, uint host, uint other)
: base(groupIndex)
{
this.charaOther = other;
work._globalTemp.host = ((ulong)host << 32) | (0xc17909);
work._globalTemp.variableCommand = 30001;
}
public uint GetHost()
{
return (uint)(((ulong)work._globalTemp.host >> 32) & 0xFFFFFFFF);
}
public uint GetOther()
{
return charaOther;
}
public override int GetMemberCount()
{
return 2;
}
public override uint GetTypeId()
{
return Group.TradeRelationGroup;
}
public ulong GetTopicGroupIndex()
{
return topicGroup;
}
public override List<GroupMember> BuildMemberList(uint id)
{
List<GroupMember> groupMembers = new List<GroupMember>();
uint hostId = (uint)((work._globalTemp.host >> 32) & 0xFFFFFFFF);
groupMembers.Add(new GroupMember(hostId, -1, 0, false, Server.GetServer().GetSession(hostId) != null, Server.GetWorldManager().GetActorInWorld(hostId).customDisplayName));
groupMembers.Add(new GroupMember(charaOther, -1, 0, false, Server.GetServer().GetSession(charaOther) != null, Server.GetWorldManager().GetActorInWorld(charaOther).customDisplayName));
return groupMembers;
}
public override void SendInitWorkValues(Session session)
{
SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex);
groupWork.addProperty(this, "work._globalTemp.host");
groupWork.addProperty(this, "work._globalTemp.variableCommand");
groupWork.setTarget("/_init");
SubPacket test = groupWork.buildPacket(session.id);
test.DebugPrintSubPacket();
session.QueuePacket(test);
}
}
}

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class ContentGroupWork
{

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class GlobalTemp
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class GroupGlobalSave
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class GroupGlobalTemp
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class GroupMemberSave
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class PartyWork
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class RelationWork
{

View file

@ -1,5 +1,4 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.lua;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;

View file

@ -1,9 +1,4 @@
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.dataobjects
{

View file

@ -1,73 +1,165 @@
using System;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.dataobjects
{
class InventoryItem
{
public const byte DEALINGMODE_NONE = 0;
public const byte DEALINGMODE_REFERENCED = 1;
public const byte DEALINGMODE_PRICED = 2;
public const byte TAG_EXCLUSIVE = 0x3;
public const byte TAG_DEALING = 0xC9;
public const byte TAG_ATTACHED = 0xCA;
public const byte TYPE_SINGLE = 11;
public const byte TYPE_MULTI = 12;
public const byte TYPE_STACK = 13;
public const byte TYPE_SEEK_ITEM = 20;
public const byte TYPE_SEEK_REPAIR = 30;
public ulong uniqueId;
public uint itemId;
public int quantity = 1;
public ushort slot;
public byte itemType;
public byte dealingVal = 0;
public byte dealingMode = DEALINGMODE_NONE;
public uint dealingAttached1 = 0;
public uint dealingAttached2 = 0;
public uint dealingAttached3 = 0;
public byte[] tags = new byte[4];
public byte[] tagValues = new byte[4];
public byte quality = 1;
public int durability = 0;
public ushort spiritbind = 0;
private ulong attachedTo = 0;
public byte materia1 = 0;
public byte materia2 = 0;
public byte materia3 = 0;
public byte materia4 = 0;
public byte materia5 = 0;
public ItemModifier modifiers;
public readonly ItemData itemData;
public Character owner = null;
public ushort slot = 0xFFFF;
public ushort itemPackage = 0xFFFF;
public class ItemModifier
{
public uint durability = 0;
public ushort use = 0;
public uint materiaId = 0;
public uint materiaLife = 0;
public byte mainQuality = 0;
public byte[] subQuality = new byte[3];
public uint polish = 0;
public uint param1 = 0;
public uint param2 = 0;
public uint param3 = 0;
public ushort spiritbind = 0;
public byte[] materiaType = new byte[5];
public byte[] materiaGrade = new byte[5];
public ItemModifier()
{
}
public ItemModifier(MySql.Data.MySqlClient.MySqlDataReader reader)
{
durability = reader.GetUInt32("durability");
mainQuality = reader.GetByte("mainQuality");
subQuality[0] = reader.GetByte("subQuality1");
subQuality[1] = reader.GetByte("subQuality2");
subQuality[2] = reader.GetByte("subQuality3");
param1 = reader.GetUInt32("param1");
param2 = reader.GetUInt32("param2");
param3 = reader.GetUInt32("param3");
spiritbind = reader.GetUInt16("spiritbind");
ushort materia1 = reader.GetUInt16("materia1");
ushort materia2 = reader.GetUInt16("materia2");
ushort materia3 = reader.GetUInt16("materia3");
ushort materia4 = reader.GetUInt16("materia4");
ushort materia5 = reader.GetUInt16("materia5");
materiaType[0] = (byte)(materia1 & 0xFF);
materiaGrade[0] = (byte)((materia1 >> 8) & 0xFF);
materiaType[1] = (byte)(materia2 & 0xFF);
materiaGrade[1] = (byte)((materia2 >> 8) & 0xFF);
materiaType[2] = (byte)(materia3 & 0xFF);
materiaGrade[2] = (byte)((materia3 >> 8) & 0xFF);
materiaType[3] = (byte)(materia4 & 0xFF);
materiaGrade[3] = (byte)((materia4 >> 8) & 0xFF);
materiaType[4] = (byte)(materia5 & 0xFF);
materiaGrade[4] = (byte)((materia5 >> 8) & 0xFF);
}
public void WriteBytes(BinaryWriter binWriter)
{
binWriter.Write((UInt32) durability);
binWriter.Write((UInt16) use);
binWriter.Write((UInt32) materiaId);
binWriter.Write((UInt32) materiaLife);
binWriter.Write((Byte) mainQuality);
binWriter.Write((Byte) subQuality[0]);
binWriter.Write((Byte) subQuality[1]);
binWriter.Write((Byte) subQuality[2]);
binWriter.Write((UInt32) polish);
binWriter.Write((UInt32) param1);
binWriter.Write((UInt32) param2);
binWriter.Write((UInt32) param3);
binWriter.Write((UInt16) spiritbind);
binWriter.Write((Byte) materiaType[0]);
binWriter.Write((Byte) materiaType[1]);
binWriter.Write((Byte) materiaType[2]);
binWriter.Write((Byte) materiaType[3]);
binWriter.Write((Byte) materiaType[4]);
binWriter.Write((Byte) materiaGrade[0]);
binWriter.Write((Byte) materiaGrade[1]);
binWriter.Write((Byte) materiaGrade[2]);
binWriter.Write((Byte) materiaGrade[3]);
binWriter.Write((Byte) materiaGrade[4]);
}
}
//Bare Minimum
public InventoryItem(uint id, uint itemId)
public InventoryItem(uint id, ItemData data)
{
this.uniqueId = id;
this.itemId = itemId;
this.itemId = data.catalogID;
this.itemData = data;
this.quantity = 1;
ItemData gItem = Server.GetItemGamedata(itemId);
itemType = gItem.isExclusive ? (byte)0x3 : (byte)0x0;
tags[1] = gItem.isExclusive ? (byte)0x3 : (byte)0x0;
}
//For check command
public InventoryItem(InventoryItem item, ushort equipSlot)
{
this.uniqueId = item.uniqueId;
this.itemData = item.itemData;
this.itemId = item.itemId;
this.quantity = item.quantity;
this.slot = equipSlot;
this.itemType = item.itemType;
this.tags = item.tags;
this.tagValues = item.tagValues;
this.quality = item.quality;
this.durability = item.durability;
this.spiritbind = item.spiritbind;
this.materia1 = item.materia1;
this.materia2 = item.materia2;
this.materia3 = item.materia3;
this.materia4 = item.materia4;
this.materia5 = item.materia5;
this.modifiers = item.modifiers;
}
public InventoryItem(uint uniqueId, uint itemId, int quantity, byte itemType, byte qualityNumber, int durability, ushort spiritbind, byte materia1, byte materia2, byte materia3, byte materia4, byte materia5)
public InventoryItem(uint uniqueId, ItemData itemData, int quantity, byte qualityNumber, ItemModifier modifiers = null)
{
this.uniqueId = uniqueId;
this.itemId = itemId;
this.itemId = itemData.catalogID;
this.itemData = itemData;
this.quantity = quantity;
this.itemType = itemType;
this.quality = qualityNumber;
this.durability = durability;
this.spiritbind = spiritbind;
this.materia1 = materia1;
this.materia2 = materia2;
this.materia3 = materia3;
this.materia4 = materia4;
this.materia5 = materia5;
this.modifiers = modifiers;
}
public byte[] ToPacketBytes()
@ -83,40 +175,161 @@ namespace FFXIVClassic_Map_Server.dataobjects
binWriter.Write((UInt32)itemId);
binWriter.Write((UInt16)slot);
binWriter.Write((UInt16)0x0001);
binWriter.Write((UInt32)0x00000000);
binWriter.Write((UInt32)0x00000000);
binWriter.Write((UInt32)0x00000000);
binWriter.Write((Byte)dealingVal);
binWriter.Write((Byte)dealingMode);
binWriter.Write((UInt32)itemType);
binWriter.Write((UInt32)dealingAttached1);
binWriter.Write((UInt32)dealingAttached2);
binWriter.Write((UInt32)dealingAttached3);
binWriter.Write((UInt32)0x00000000);
for (int i = 0; i < tags.Length; i++)
binWriter.Write((Byte) tags[i]);
for (int i = 0; i < tagValues.Length; i++)
binWriter.Write((Byte) tagValues[i]);
binWriter.Write((byte)quality);
binWriter.Write((byte)0x01);
binWriter.Write((uint)durability);
binWriter.Write((Byte)quality);
binWriter.BaseStream.Seek(0x10-0x06, SeekOrigin.Current);
binWriter.Write((byte)0x01);
binWriter.Write((byte)0x01);
binWriter.Write((byte)0x01);
binWriter.Write((byte)0x01);
binWriter.BaseStream.Seek(0x10, SeekOrigin.Current);
binWriter.Write((ushort)spiritbind);
binWriter.Write((byte)materia1);
binWriter.Write((byte)materia2);
binWriter.Write((byte)materia3);
binWriter.Write((byte)materia4);
binWriter.Write((byte)materia5);
if (modifiers != null)
{
binWriter.Write((Byte)0x01);
modifiers.WriteBytes(binWriter);
}
}
}
return data;
}
public void SetQuantity(uint quantity)
{
lock (owner.GetItemPackage(itemPackage))
{
this.quantity = (int)quantity;
if (quantity < 0)
quantity = 0;
Database.SetQuantity(uniqueId, this.quantity);
if (owner != null && owner is Player)
owner.GetItemPackage(itemPackage).RefreshItem((Player)owner, this);
}
}
public void ChangeQuantity(int quantityDelta)
{
lock (owner.GetItemPackage(itemPackage))
{
this.quantity += quantityDelta;
if (quantity < 0)
quantity = 0;
if (quantity == 0)
{
owner.RemoveItem(this);
return;
}
Database.SetQuantity(uniqueId, this.quantity);
if (owner != null && owner is Player)
{
((Player)owner).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId, false));
owner.GetItemPackage(itemPackage).RefreshItem((Player)owner, this);
((Player)owner).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
}
}
}
public void RefreshPositioning(Character owner, ushort itemPackage, ushort slot)
{
this.owner = owner;
this.itemPackage = itemPackage;
this.slot = slot;
}
public void SetExclusive(bool isExclusive)
{
tags[1] = isExclusive ? TAG_EXCLUSIVE : (byte)0;
}
public void SetHasAttached(bool isAttached)
{
tags[0] = isAttached ? TAG_ATTACHED : (byte)0;
}
public void SetNormal()
{
for (int i = 0; i < 4; i++)
{
if (tags[i] == TAG_DEALING || tags[i] == TAG_ATTACHED)
{
tags[i] = 0;
tagValues[i] = 0;
attachedTo = 0;
dealingVal = 0;
dealingMode = 0;
dealingAttached1 = 0;
dealingAttached2 = 0;
dealingAttached3 = 0;
}
}
}
public void SetDealing(byte mode, int price)
{
tags[0] = TAG_DEALING;
tagValues[0] = mode;
if (mode == TYPE_SINGLE || mode == TYPE_MULTI || mode == TYPE_STACK)
{
dealingVal = 1;
dealingMode = DEALINGMODE_PRICED;
dealingAttached1 = 1;
dealingAttached2 = (uint) price;
dealingAttached3 = 0;
}
}
public void SetDealingAttached(byte mode, ulong attached)
{
tags[0] = TAG_DEALING;
tagValues[0] = mode;
attachedTo = attached;
}
public ulong GetAttached()
{
return attachedTo;
}
public void SetAttachedIndex(ushort package, ushort index)
{
dealingVal = 1;
dealingMode = DEALINGMODE_REFERENCED;
dealingAttached1 = (uint)((package << 16) | index);
dealingAttached2 = 0;
dealingAttached3 = 0;
}
public ItemData GetItemData()
{
return itemData;
}
public byte GetBazaarMode()
{
for (int i = 0; i < tags.Length; i++)
{
if (tags[i] == 0xC9)
return tagValues[i];
}
return 0;
}
public bool IsSelling()
{
return GetBazaarMode() == TYPE_SINGLE || GetBazaarMode() == TYPE_MULTI || GetBazaarMode() == TYPE_STACK;
}
}
}

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.dataobjects
namespace FFXIVClassic_Map_Server.dataobjects
{
class SeamlessBoundry
{

View file

@ -0,0 +1,3 @@
namespace FFXIVClassic_Map_Server.dataobjects
{
}

View file

@ -4,7 +4,6 @@ using System.Net.Sockets;
using FFXIVClassic.Common;
using System.Collections.Concurrent;
using System.Net;
using System.Collections.Generic;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
namespace FFXIVClassic_Map_Server.dataobjects
@ -19,7 +18,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void QueuePacket(SubPacket subpacket)
{
if(SendPacketQueue.Count == 1000)
if (SendPacketQueue.Count == SendPacketQueue.BoundedCapacity - 1)
FlushQueuedSendPackets();
SendPacketQueue.Add(subpacket);

View file

@ -11,8 +11,6 @@ using MoonSharp.Interpreter.Loaders;
using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area;
using System.Threading;
@ -93,7 +91,7 @@ namespace FFXIVClassic_Map_Server.lua
}
}
public void OnSignal(string signal)
public void OnSignal(string signal, params object[] args)
{
List<Coroutine> mToAwake = new List<Coroutine>();
@ -105,7 +103,7 @@ namespace FFXIVClassic_Map_Server.lua
foreach (Coroutine key in mToAwake)
{
DynValue value = key.Resume();
DynValue value = key.Resume(args);
ResolveResume(null, key, value);
}
}
@ -642,6 +640,7 @@ namespace FFXIVClassic_Map_Server.lua
public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false)
{
bool playerNull = player == null;
if (playerNull)
{
if (param.Length >= 2 && param[1].Contains("\""))
@ -649,6 +648,10 @@ namespace FFXIVClassic_Map_Server.lua
else if (param.Length > 2)
player = Server.GetWorldManager().GetPCInWorld(param[1] + param[2]);
}
if (playerNull && param.Length >= 3)
player = Server.GetWorldManager().GetPCInWorld(param[1] + " " + param[2]);
// load from scripts/commands/gm/ directory
var path = String.Format("./scripts/commands/gm/{0}.lua", cmd.ToLower());

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MoonSharp;
using MoonSharp.Interpreter;
using NLog;
using MoonSharp.Interpreter.Debugging;

View file

@ -12,19 +12,37 @@ namespace FFXIVClassic_Map_Server
class LuaUtils
{
public class Type7Param
public class ItemRefParam
{
public uint actorId;
public byte unknown;
public byte slot;
public byte inventoryType;
public byte itemPackage;
public Type7Param(uint actorId, byte unknown, byte slot, byte inventoryType)
public ItemRefParam(uint actorId, byte unknown, byte slot, byte itemPackage)
{
this.actorId = actorId;
this.unknown = unknown;
this.slot = slot;
this.inventoryType = inventoryType;
this.itemPackage = itemPackage;
}
}
public class ItemOfferParam
{
public uint actorId;
public ushort offerSlot;
public ushort unknown1;
public ushort seekSlot;
public ushort unknown2;
public ItemOfferParam(uint actorId, ushort unknown1, ushort offerSlot, ushort seekSlot, ushort unknown2)
{
this.actorId = actorId;
this.unknown1 = unknown1;
this.offerSlot = offerSlot;
this.seekSlot = seekSlot;
this.unknown2 = unknown2;
}
}
@ -81,12 +99,24 @@ namespace FFXIVClassic_Map_Server
case 0x6: //Actor (By Id)
value = Utils.SwapEndian(reader.ReadUInt32());
break;
case 0x7: //Weird one used for inventory
case 0x7: //Item Reference to Inventory Spot
{
uint type7ActorId = Utils.SwapEndian(reader.ReadUInt32());
byte type7Unknown = reader.ReadByte();
byte type7Slot = reader.ReadByte();
byte type7InventoryType = reader.ReadByte();
value = new Type7Param(type7ActorId, type7Unknown, type7Slot, type7InventoryType);
value = new ItemRefParam(type7ActorId, type7Unknown, type7Slot, type7InventoryType);
}
break;
case 0x8: //Used for offering
{
uint actorId = Utils.SwapEndian(reader.ReadUInt32());
ushort unk1 = Utils.SwapEndian(reader.ReadUInt16());
ushort offerSlot = Utils.SwapEndian(reader.ReadUInt16());
ushort seekSlot = Utils.SwapEndian(reader.ReadUInt16());
ushort unk2 = Utils.SwapEndian(reader.ReadUInt16());
value = new ItemOfferParam(actorId, unk1, offerSlot, seekSlot, unk2);
}
break;
case 0x9: //Two Longs (only storing first one)
value = new Type9Param(Utils.SwapEndian(reader.ReadUInt64()), Utils.SwapEndian(reader.ReadUInt64()));
@ -105,7 +135,13 @@ namespace FFXIVClassic_Map_Server
if (isDone)
break;
if (value != null)
//Special case cause fuck Type8
if (value != null && value is ItemOfferParam)
{
luaParams.Add(new LuaParam(code, value));
luaParams.Add(new LuaParam(5, null));
}
else if (value != null)
luaParams.Add(new LuaParam(code, value));
else if (wasNil)
luaParams.Add(new LuaParam(code, value));
@ -152,11 +188,11 @@ namespace FFXIVClassic_Map_Server
writer.Write((UInt32)Utils.SwapEndian((UInt32)l.value));
break;
case 0x7: //Weird one used for inventory
Type7Param type7 = (Type7Param)l.value;
ItemRefParam type7 = (ItemRefParam)l.value;
writer.Write((UInt32)Utils.SwapEndian((UInt32)type7.actorId));
writer.Write((Byte)type7.unknown);
writer.Write((Byte)type7.slot);
writer.Write((Byte)type7.inventoryType);
writer.Write((Byte)type7.itemPackage);
break;
case 0x9: //Two Longs (only storing first one)
writer.Write((UInt64)Utils.SwapEndian(((Type9Param)l.value).item1));
@ -226,7 +262,7 @@ namespace FFXIVClassic_Map_Server
byte type7Unknown = reader.ReadByte();
byte type7Slot = reader.ReadByte();
byte type7InventoryType = reader.ReadByte();
value = new Type7Param(type7ActorId, type7Unknown, type7Slot, type7InventoryType);
value = new ItemRefParam(type7ActorId, type7Unknown, type7Slot, type7InventoryType);
break;
case 0x9: //Two Longs (only storing first one)
value = new Type9Param(Utils.SwapEndian(reader.ReadUInt64()), Utils.SwapEndian(reader.ReadUInt64()));
@ -359,9 +395,13 @@ namespace FFXIVClassic_Map_Server
{
luaParams.Add(new LuaParam(0x6, ((Actor)o).actorId));
}
else if (o is Type7Param)
else if (o is ItemRefParam)
{
luaParams.Add(new LuaParam(0x7, (Type7Param)o));
luaParams.Add(new LuaParam(0x7, (ItemRefParam)o));
}
else if (o is ItemOfferParam)
{
luaParams.Add(new LuaParam(0x8, (ItemOfferParam)o));
}
else if (o is Type9Param)
{
@ -416,16 +456,20 @@ namespace FFXIVClassic_Map_Server
dumpString += String.Format("0x{0:X}", (uint)lParams[i].value);
break;
case 0x7: //Weird one used for inventory
Type7Param type7Param = ((Type7Param)lParams[i].value);
dumpString += String.Format("Type7 Param: (0x{0:X}, 0x{1:X}, 0x{2:X}, 0x{3:X})", type7Param.actorId, type7Param.unknown, type7Param.slot, type7Param.inventoryType);
ItemRefParam type7Param = ((ItemRefParam)lParams[i].value);
dumpString += String.Format("Type7 Param: (0x{0:X}, 0x{1:X}, 0x{2:X}, 0x{3:X})", type7Param.actorId, type7Param.unknown, type7Param.slot, type7Param.itemPackage);
break;
case 0xC: //Byte
dumpString += String.Format("0x{0:X}", (byte)lParams[i].value);
case 0x8: //Weird one used for inventory
ItemOfferParam itemOfferParam = ((ItemOfferParam)lParams[i].value);
dumpString += String.Format("Type8 Param: (0x{0:X}, 0x{1:X}, 0x{2:X}, 0x{3:X}, 0x{4:X})", itemOfferParam.actorId, itemOfferParam.unknown1, itemOfferParam.offerSlot, itemOfferParam.seekSlot, itemOfferParam.unknown2);
break;
case 0x9: //Long (+ 8 bytes ignored)
Type9Param type9Param = ((Type9Param)lParams[i].value);
dumpString += String.Format("Type9 Param: (0x{0:X}, 0x{1:X})", type9Param.item1, type9Param.item2);
break;
case 0xC: //Byte
dumpString += String.Format("0x{0:X}", (byte)lParams[i].value);
break;
case 0x1B: //Short?
dumpString += String.Format("0x{0:X}", (ushort)lParams[i].value);
break;

View file

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{

View file

@ -0,0 +1,31 @@
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{
class LinkshellResultPacket
{
public int resultCode;
public bool invalidPacket = false;
public LinkshellResultPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
resultCode = binReader.ReadInt32();
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View file

@ -1,10 +1,5 @@
using FFXIVClassic_Map_Server.actors.group;
using System;
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{

View file

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{

View file

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{

View file

@ -1,7 +1,6 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
@ -20,6 +19,7 @@ namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
binWriter.BaseStream.Seek(0x20, SeekOrigin.Begin);
binWriter.Write((UInt16)crest);
binWriter.Write((UInt32)master);
}

View file

@ -1,6 +1,5 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.IO;
using System.Text;

View file

@ -1,11 +1,7 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{

View file

@ -1,8 +1,5 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

View file

@ -1,11 +1,5 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{

View file

@ -1,11 +1,8 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{

View file

@ -1,8 +1,6 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

View file

@ -1,8 +1,6 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

View file

@ -1,11 +1,8 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{

View file

@ -1,10 +1,7 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{

View file

@ -1,8 +1,6 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

View file

@ -1,10 +1,6 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send
{

View file

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.receive
{

View file

@ -0,0 +1,29 @@
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.receive
{
class UpdateItemPackagePacket
{
public bool invalidPacket = false;
public uint actorID;
public uint packageId;
public UpdateItemPackagePacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try{
actorID = binReader.ReadUInt32();
packageId = binReader.ReadUInt32();
}
catch (Exception){
invalidPacket = true;
}
}
}
}
}
}

View file

@ -1,9 +1,5 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor
{

View file

@ -110,6 +110,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
{
string[] split = name.Split('.');
int arrayIndex = 0;
if (!(split[0].Equals("work") || split[0].Equals("charaWork") || split[0].Equals("playerWork") || split[0].Equals("npcWork") || split[0].Equals("guildleveWork")))
return false;

View file

@ -0,0 +1,12 @@
namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{
class BattleAction
{
public uint targetId;
public ushort amount;
public ushort worldMasterTextId;
public uint effectId;
public byte param;
public byte unknown;
}
}

View file

@ -0,0 +1,59 @@
using FFXIVClassic.Common;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{
class BattleActionX10Packet
{
public const ushort OPCODE = 0x013A;
public const uint PACKET_SIZE = 0xD8;
public static SubPacket BuildPacket(uint playerActorID, uint sourceActorId, uint animationId, ushort commandId, BattleAction[] actionList)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)sourceActorId);
binWriter.Write((UInt32)animationId);
//Missing... last value is float, string in here as well?
binWriter.Seek(0x20, SeekOrigin.Begin);
binWriter.Write((UInt32) actionList.Length); //Num actions (always 1 for this)
binWriter.Write((UInt16)commandId);
binWriter.Write((UInt16)810); //?
binWriter.Seek(0x20, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt32)action.targetId);
binWriter.Seek(0x50, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt16)action.amount);
binWriter.Seek(0x64, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt16)action.worldMasterTextId);
binWriter.Seek(0x78, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt32)action.effectId);
binWriter.Seek(0xA0, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((Byte)action.param);
binWriter.Seek(0xAA, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((Byte)action.unknown);
}
}
return new SubPacket(OPCODE, sourceActorId, data);
}
}
}

View file

@ -0,0 +1,59 @@
using FFXIVClassic.Common;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{
class BattleActionX18Packet
{
public const ushort OPCODE = 0x013B;
public const uint PACKET_SIZE = 0x148;
public static SubPacket BuildPacket(uint playerActorID, uint sourceActorId, uint animationId, ushort commandId, BattleAction[] actionList)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)sourceActorId);
binWriter.Write((UInt32)animationId);
//Missing... last value is float, string in here as well?
binWriter.Seek(0x20, SeekOrigin.Begin);
binWriter.Write((UInt32) actionList.Length); //Num actions (always 1 for this)
binWriter.Write((UInt16)commandId);
binWriter.Write((UInt16)810); //?
binWriter.Seek(0x58, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt32)action.targetId);
binWriter.Seek(0xA0, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt16)action.amount);
binWriter.Seek(0xC4, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt16)action.worldMasterTextId);
binWriter.Seek(0xE8, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((UInt32)action.effectId);
binWriter.Seek(0x130, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((Byte)action.param);
binWriter.Seek(0x142, SeekOrigin.Begin);
foreach (BattleAction action in actionList)
binWriter.Write((Byte)action.unknown);
}
}
return new SubPacket(OPCODE, sourceActorId, data);
}
}
}

View file

@ -7,16 +7,13 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
public const ushort OPCODE = 0x016D;
public const uint PACKET_SIZE = 0x28;
public static SubPacket BuildPacket(uint sourceActorId, uint targetActorId)
public static SubPacket BuildPacket(uint playerActorID, bool clearItemPackage = false)
{
byte[] data = new byte[8];
data[0] = 2;
return new SubPacket(OPCODE, sourceActorId, data);
}
public static SubPacket BuildPacket(uint playerActorID)
{
byte[] data = new byte[8];
if (clearItemPackage)
data[0] = 2;
return new SubPacket(OPCODE, playerActorID, data);
}
}

View file

@ -13,7 +13,7 @@ namespace FFXIVClassic_Map_Server.packets.send.events
public const ushort OPCODE = 0x012F;
public const uint PACKET_SIZE = 0x90;
public static SubPacket BuildPacket(uint sourcePlayerActorId, uint targetEventActorId, string conditionName, List<LuaParam> luaParams)
public static SubPacket BuildPacket(uint sourcePlayerActorId, uint targetEventActorId, uint unknown, string conditionName, List<LuaParam> luaParams)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
@ -23,10 +23,7 @@ namespace FFXIVClassic_Map_Server.packets.send.events
{
binWriter.Write((UInt32)sourcePlayerActorId);
binWriter.Write((UInt32)targetEventActorId);
int test = 0x75dc1705; //This will crash if set to 0 on pushCommand but not for mining which has to be 0????
binWriter.Write((UInt32)test);
binWriter.Write((UInt32)unknown);
binWriter.Write((UInt32)0x30400000);
binWriter.Write(Encoding.ASCII.GetBytes(conditionName), 0, Encoding.ASCII.GetByteCount(conditionName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(conditionName));

View file

@ -2,9 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -1,12 +1,8 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -1,12 +1,8 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -1,11 +1,7 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.groups
{

View file

@ -1,12 +1,8 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -1,6 +1,4 @@
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.group
namespace FFXIVClassic_Map_Server.packets.send.group
{
class GroupMember
{

View file

@ -1,12 +1,7 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -1,12 +1,7 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -2,9 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.group
{

View file

@ -1,12 +1,10 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.groups
{

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.search
namespace FFXIVClassic_Map_Server.packets.send.search
{
class ItemSearchResult
{

View file

@ -1,6 +1,4 @@
using System.IO;
using System.Text;

using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.search

View file

@ -1,5 +1,4 @@
using System.IO;
using System.Text;
using System;
using FFXIVClassic.Common;
using System.Collections.Generic;

View file

@ -1,6 +1,4 @@
using System.IO;
using System.Text;

using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.search

Some files were not shown because too many files have changed in this diff Show more