Compare commits

..

5 Commits

76 changed files with 943 additions and 10477 deletions
+1 -13
View File
@@ -112,8 +112,6 @@ SET(common_sources
net/websocket_server.cpp
net/websocket_server_connection.cpp
patches/patches.cpp
patches/laurion.cpp
patches/laurion_limits.cpp
patches/sod.cpp
patches/sod_limits.cpp
patches/sof.cpp
@@ -657,11 +655,7 @@ SET(common_headers
net/websocket_server.h
net/websocket_server_connection.h
patches/patches.h
patches/laurion.h
patches/laurion_limits.h
patches/laurion_ops.h
patches/laurion_structs.h
patches/sod.h
patches/sod.h
patches/sod_limits.h
patches/sod_ops.h
patches/sod_structs.h
@@ -747,10 +741,6 @@ SOURCE_GROUP(Net FILES
SOURCE_GROUP(Patches FILES
patches/patches.h
patches/laurion.h
patches/laurion_limits.h
patches/laurion_ops.h
patches/laurion_structs.h
patches/sod.h
patches/sod_limits.h
patches/sod_ops.h
@@ -779,8 +769,6 @@ SOURCE_GROUP(Patches FILES
patches/uf_ops.h
patches/uf_structs.h
patches/patches.cpp
patches/laurion.cpp
patches/laurion_limits.cpp
patches/sod.cpp
patches/sod_limits.cpp
patches/sof.cpp
-1
View File
@@ -59,7 +59,6 @@ public:
void WriteUInt8(uint8 value) { *(uint8 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint8); }
void WriteUInt32(uint32 value) { *(uint32 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint32); }
void WriteUInt64(uint64 value) { *(uint64 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint64); }
void WriteSInt16(int32 value) { *(int16*)(pBuffer + _wpos) = value; _wpos += sizeof(int16); }
void WriteUInt16(uint32 value) { *(uint16 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint16); }
void WriteSInt32(int32 value) { *(int32 *)(pBuffer + _wpos) = value; _wpos += sizeof(int32); }
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
-3
View File
@@ -71,9 +71,6 @@ namespace Class {
constexpr uint8 FellowshipMaster = 69;
constexpr uint8 AlternateCurrencyMerchant = 70;
constexpr uint8 MercenaryLiaison = 71;
constexpr uint8 RealEstateMerchant = 72;
constexpr uint8 LoyaltyMerchant = 73;
constexpr uint8 TributeMaster2 = 74;
constexpr uint8 PLAYER_CLASS_COUNT = 16;
constexpr uint16 ALL_CLASSES_BITMASK = 65535;
-18
View File
@@ -101,24 +101,6 @@ void CRC32::SetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at)
memcpy(in_data, (char*)&check, 4);
}
unsigned long CRC32::GetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at)
{
unsigned long data;
unsigned long check = 0xffffffff;
for (uint32 i = start_at; i < in_length; i++)
{
data = in_data[i];
data = data ^ (check);
data = data & 0x000000ff;
check = check >> 8;
data = CRC32Table[data];
check = check ^ data;
}
return check;
}
uint32 CRC32::Update(const uint8* buf, uint32 bufsize, uint32 crc32var) {
for(uint32 i=0; i < bufsize; i++)
Calc(buf[i], crc32var);
-1
View File
@@ -8,7 +8,6 @@ public:
static uint32 Generate(const uint8* buf, uint32 bufsize);
static uint32 GenerateNoFlip(const uint8* buf, uint32 bufsize); // Same as Generate(), but without the ~
static void SetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at=4);
static unsigned long GetEQChecksum(uchar* in_data, uint32 in_length, uint32 start_at = 4);
// Multiple buffer CRC32
static uint32 Update(const uint8* buf, uint32 bufsize, uint32 crc32 = 0xFFFFFFFF);
+3 -2
View File
@@ -1,6 +1,8 @@
// system use
N(OP_ExploreUnknown),
// start (please add new opcodes in descending order and re-order any name changes where applicable)
N(OP_0x0193),
N(OP_0x0347),
N(OP_AAAction),
N(OP_AAExpUpdate),
N(OP_AcceptNewTask),
@@ -354,7 +356,6 @@ N(OP_MercenaryTimer),
N(OP_MercenaryTimerRequest),
N(OP_MercenaryUnknown1),
N(OP_MercenaryUnsuspendResponse),
N(OP_MerchantBulkItems),
N(OP_MobEnduranceUpdate),
N(OP_MobHealth),
N(OP_MobManaUpdate),
@@ -373,7 +374,6 @@ N(OP_MultiLineMsg),
N(OP_NewSpawn),
N(OP_NewTitlesAvailable),
N(OP_NewZone),
N(OP_NPCMoveUpdate),
N(OP_OnLevelMessage),
N(OP_OpenContainer),
N(OP_OpenDiscordMerchant),
@@ -465,6 +465,7 @@ N(OP_SendAAStats),
N(OP_SendAATable),
N(OP_SendCharInfo),
N(OP_SendExpZonein),
N(OP_SendFindableLocations),
N(OP_SendFindableNPCs),
N(OP_SendGuildTributes),
N(OP_SendLoginInfo),
-103
View File
@@ -56,8 +56,6 @@ const char* EQ::versions::ClientVersionName(ClientVersion client_version)
return "RoF";
case ClientVersion::RoF2:
return "RoF2";
case ClientVersion::Laurion:
return "Laurion";
default:
return "Invalid Version";
};
@@ -78,8 +76,6 @@ uint32 EQ::versions::ConvertClientVersionToClientVersionBit(ClientVersion client
return bitRoF;
case ClientVersion::RoF2:
return bitRoF2;
case ClientVersion::Laurion:
return bitLaurion;
default:
return bitUnknown;
}
@@ -100,8 +96,6 @@ EQ::versions::ClientVersion EQ::versions::ConvertClientVersionBitToClientVersion
return ClientVersion::RoF;
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::RoF2) - 1)) :
return ClientVersion::RoF2;
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Laurion) - 1)):
return ClientVersion::Laurion;
default:
return ClientVersion::Unknown;
}
@@ -190,8 +184,6 @@ const char* EQ::versions::MobVersionName(MobVersion mob_version)
return "RoF";
case MobVersion::RoF2:
return "RoF2";
case MobVersion::Laurion:
return "Laurion";
case MobVersion::NPC:
return "NPC";
case MobVersion::NPCMerchant:
@@ -220,8 +212,6 @@ const char* EQ::versions::MobVersionName(MobVersion mob_version)
return "Offline RoF";
case MobVersion::OfflineRoF2:
return "Offline RoF2";
case MobVersion::OfflineLaurion:
return "Offline Laurion";
default:
return "Invalid Version";
};
@@ -245,8 +235,6 @@ EQ::versions::ClientVersion EQ::versions::ConvertMobVersionToClientVersion(MobVe
return ClientVersion::RoF;
case MobVersion::RoF2:
return ClientVersion::RoF2;
case MobVersion::Laurion:
return ClientVersion::Laurion;
default:
return ClientVersion::Unknown;
}
@@ -270,8 +258,6 @@ EQ::versions::MobVersion EQ::versions::ConvertClientVersionToMobVersion(ClientVe
return MobVersion::RoF;
case ClientVersion::RoF2:
return MobVersion::RoF2;
case ClientVersion::Laurion:
return MobVersion::Laurion;
default:
return MobVersion::Unknown;
}
@@ -292,8 +278,6 @@ EQ::versions::MobVersion EQ::versions::ConvertPCMobVersionToOfflinePCMobVersion(
return MobVersion::OfflineRoF;
case MobVersion::RoF2:
return MobVersion::OfflineRoF2;
case MobVersion::Laurion:
return MobVersion::OfflineLaurion;
default:
return MobVersion::Unknown;
}
@@ -314,8 +298,6 @@ EQ::versions::MobVersion EQ::versions::ConvertOfflinePCMobVersionToPCMobVersion(
return MobVersion::RoF;
case MobVersion::OfflineRoF2:
return MobVersion::RoF2;
case MobVersion::OfflineLaurion:
return MobVersion::Laurion;
default:
return MobVersion::Unknown;
}
@@ -336,8 +318,6 @@ EQ::versions::ClientVersion EQ::versions::ConvertOfflinePCMobVersionToClientVers
return ClientVersion::RoF;
case MobVersion::OfflineRoF2:
return ClientVersion::RoF2;
case MobVersion::OfflineLaurion:
return ClientVersion::Laurion;
default:
return ClientVersion::Unknown;
}
@@ -358,8 +338,6 @@ EQ::versions::MobVersion EQ::versions::ConvertClientVersionToOfflinePCMobVersion
return MobVersion::OfflineRoF;
case ClientVersion::RoF2:
return MobVersion::OfflineRoF2;
case ClientVersion::Laurion:
return MobVersion::OfflineLaurion;
default:
return MobVersion::Unknown;
}
@@ -410,27 +388,6 @@ const char* EQ::expansions::ExpansionName(Expansion expansion)
return "Rain of Fear";
case Expansion::CotF:
return "Call of the Forsaken";
case Expansion::TDS:
return "The Darkened Sea";
case Expansion::TBM:
return "The Broken Mirror";
case Expansion::EoK:
return "Empires of Kunark";
case Expansion::RoS:
return "Ring of Scale";
case Expansion::TBL:
return "The Burning Lands";
case Expansion::ToV:
return "Torment of Velious";
case Expansion::CoV:
return "Claws of Veeshan";
case Expansion::ToL:
return "Terror of Luclin";
case Expansion::NoS:
return "Night of Shadows";
case Expansion::LS:
return "Laurion's Song";
default:
return "Invalid Expansion";
}
@@ -484,26 +441,6 @@ uint32 EQ::expansions::ConvertExpansionToExpansionBit(Expansion expansion)
return bitRoF;
case Expansion::CotF:
return bitCotF;
case Expansion::TDS:
return bitTDS;
case Expansion::TBM:
return bitTBM;
case Expansion::EoK:
return bitEoK;
case Expansion::RoS:
return bitRoS;
case Expansion::TBL:
return bitTBL;
case Expansion::ToV:
return bitToV;
case Expansion::CoV:
return bitCoV;
case Expansion::ToL:
return bitToL;
case Expansion::NoS:
return bitNoS;
case Expansion::LS:
return bitLS;
default:
return bitEverQuest;
}
@@ -552,26 +489,6 @@ EQ::expansions::Expansion EQ::expansions::ConvertExpansionBitToExpansion(uint32
return Expansion::RoF;
case bitCotF:
return Expansion::CotF;
case bitTDS:
return Expansion::TDS;
case bitTBM:
return Expansion::TBM;
case bitEoK:
return Expansion::EoK;
case bitRoS:
return Expansion::RoS;
case bitTBL:
return Expansion::TBL;
case bitToV:
return Expansion::ToV;
case bitCoV:
return Expansion::CoV;
case bitToL:
return Expansion::ToL;
case bitNoS:
return Expansion::NoS;
case bitLS:
return Expansion::LS;
default:
return Expansion::EverQuest;
}
@@ -620,26 +537,6 @@ uint32 EQ::expansions::ConvertExpansionToExpansionsMask(Expansion expansion)
return maskRoF;
case Expansion::CotF:
return maskCotF;
case Expansion::TDS:
return maskTDS;
case Expansion::TBM:
return maskTBM;
case Expansion::EoK:
return maskEoK;
case Expansion::RoS:
return maskRoS;
case Expansion::TBL:
return maskTBL;
case Expansion::ToV:
return maskToV;
case Expansion::CoV:
return maskCoV;
case Expansion::ToL:
return maskToL;
case Expansion::NoS:
return maskNoS;
case Expansion::LS:
return maskLS;
default:
return maskEverQuest;
}
+9 -45
View File
@@ -36,8 +36,7 @@ namespace EQ
SoD, // Build: 'Dec 19 2008 15:22:49'
UF, // Build: 'Jun 8 2010 16:44:32'
RoF, // Build: 'Dec 10 2012 17:35:44'
RoF2, // Build: 'May 10 2013 23:30:08'
Laurion
RoF2 // Build: 'May 10 2013 23:30:08'
};
enum ClientVersionBitmask : uint32 {
@@ -49,7 +48,6 @@ namespace EQ
bitUF = 0x00000010,
bitRoF = 0x00000020,
bitRoF2 = 0x00000040,
bitLaurion = 0x00000080,
maskUnknown = 0x00000000,
maskTitaniumAndEarlier = 0x00000003,
maskSoFAndEarlier = 0x00000007,
@@ -61,11 +59,10 @@ namespace EQ
maskUFAndLater = 0xFFFFFFF0,
maskRoFAndLater = 0xFFFFFFE0,
maskRoF2AndLater = 0xFFFFFFC0,
maskLaurionAndLater = 0xFFFFFF80,
maskAllClients = 0xFFFFFFFF
};
const ClientVersion LastClientVersion = ClientVersion::Laurion;
const ClientVersion LastClientVersion = ClientVersion::RoF2;
const size_t ClientVersionCount = (static_cast<size_t>(LastClientVersion) + 1);
bool IsValidClientVersion(ClientVersion client_version);
@@ -83,7 +80,6 @@ namespace EQ
UF,
RoF,
RoF2,
Laurion,
NPC,
NPCMerchant,
Merc,
@@ -97,14 +93,13 @@ namespace EQ
OfflineSoD,
OfflineUF,
OfflineRoF,
OfflineRoF2,
OfflineLaurion
OfflineRoF2
};
const MobVersion LastMobVersion = MobVersion::OfflineLaurion;
const MobVersion LastPCMobVersion = MobVersion::Laurion;
const MobVersion LastMobVersion = MobVersion::OfflineRoF2;
const MobVersion LastPCMobVersion = MobVersion::RoF2;
const MobVersion LastNonPCMobVersion = MobVersion::BotPet;
const MobVersion LastOfflinePCMobVersion = MobVersion::OfflineLaurion;
const MobVersion LastOfflinePCMobVersion = MobVersion::OfflineRoF2;
const size_t MobVersionCount = (static_cast<size_t>(LastMobVersion) + 1);
bool IsValidMobVersion(MobVersion mob_version);
@@ -136,8 +131,7 @@ namespace EQ
ucsSoDCombined = 'D',
ucsUFCombined = 'E',
ucsRoFCombined = 'F',
ucsRoF2Combined = 'G',
ucsLaurionCombined = 'G'
ucsRoF2Combined = 'G'
};
} /*versions*/
@@ -164,17 +158,7 @@ namespace EQ
HoT,
VoA,
RoF,
CotF,
TDS,
TBM,
EoK,
RoS,
TBL,
ToV,
CoV,
ToL,
NoS,
LS
CotF
};
enum ExpansionBitmask : uint32 {
@@ -199,16 +183,6 @@ namespace EQ
bitVoA = 0x00020000,
bitRoF = 0x00040000,
bitCotF = 0x00080000,
bitTDS = 0x00100000,
bitTBM = 0x00200000,
bitEoK = 0x00400000,
bitRoS = 0x00800000,
bitTBL = 0x01000000,
bitToV = 0x02000000,
bitCoV = 0x04000000,
bitToL = 0x08000000,
bitNoS = 0x10000000,
bitLS = 0x20000000,
maskEverQuest = 0x00000000,
maskRoK = 0x00000001,
maskSoV = 0x00000003,
@@ -229,17 +203,7 @@ namespace EQ
maskHoT = 0x0001FFFF,
maskVoA = 0x0003FFFF,
maskRoF = 0x0007FFFF,
maskCotF = 0x000FFFFF,
maskTDS = 0x001FFFFF,
maskTBM = 0x003FFFFF,
maskEoK = 0x007FFFFF,
maskRoS = 0x00FFFFFF,
maskTBL = 0x01FFFFFF,
maskToV = 0x03FFFFFF,
maskCoV = 0x07FFFFFF,
maskToL = 0x0FFFFFFF,
maskNoS = 0x1FFFFFFF,
maskLS = 0x3FFFFFFF,
maskCotF = 0x000FFFFF
};
const char* ExpansionName(Expansion expansion);
-40
View File
@@ -762,46 +762,6 @@ typedef enum {
FilterStrikethrough = 26, //0=show, 1=hide // RoF2 Confirmed
FilterStuns = 27, //0=show, 1=hide // RoF2 Confirmed
FilterBardSongsOnPets = 28, //0=show, 1=hide // RoF2 Confirmed
FilterSwarmPetDeath = 29,
FilterFellowshipChat = 30,
FilterMercenaryMessages = 31,
FilterSpam = 32,
FilterAchievements = 33,
FilterPvPMessages = 34,
FilterSpellNameInCast = 35,
FilterRandomMine = 36,
FilterRandomGroupRaid = 37,
FilterRandomOthers = 38,
FilterEnvironmentalDamage = 39,
FilterMessages = 40,
FilterOverwriteDetrimental = 41,
FilterOverwriteBeneficial = 42,
FilterCantUseCommand = 43,
FilterCombatAbilityReuse = 44,
FilterAAAbilityReuse = 45,
FilterProcBeginCasting = 46,
FilterDestroyedItems = 47,
FilterYourAuras = 48,
FilterOtherAuras = 49,
FilterYourHeals = 50,
FilterOtherHeals = 51,
FilterYourDoTs = 52,
FilterOtherDoTs = 53,
FilterOtherDirectDamage = 54,
FilterSpellEmotes = 55,
FilterFactionMessages = 56,
FilterTauntMessages = 57,
FilterYourDisciplines = 58,
FilterOtherDisplines = 59,
FilterAchievementsOthers = 60,
FilterRaidVictory = 61,
FilterOtherDirectDamageCrits = 62,
FilterDoTYoursCritical = 63,
FilterDoTOthersCritical = 64,
FilterDoTDamageTaken = 65,
FilterHealsReceived = 66,
FilterHealsYoursCritical = 67,
FilterHealsOthersCritical = 68,
_FilterCount
} eqFilterType;
-83
View File
@@ -104,14 +104,6 @@ static const EQ::constants::LookupEntry constants_static_lookup_entries[EQ::vers
RoF2::constants::EXPANSIONS_MASK,
RoF2::constants::CHARACTER_CREATION_LIMIT,
RoF2::constants::SAY_LINK_BODY_SIZE
),
/*[ClientVersion::Laurion] =*/
EQ::constants::LookupEntry(
Laurion::constants::EXPANSION,
Laurion::constants::EXPANSION_BIT,
Laurion::constants::EXPANSIONS_MASK,
Laurion::constants::CHARACTER_CREATION_LIMIT,
Laurion::constants::SAY_LINK_BODY_SIZE
)
};
@@ -378,33 +370,6 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
RoF2::inventory::ConcatenateInvTypeLimbo,
RoF2::inventory::AllowOverLevelEquipment
),
/*[MobVersion::LS] =*/
EQ::inventory::LookupEntry(
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
EQ::invtype::POSSESSIONS_SIZE, RoF2::invtype::BANK_SIZE, RoF2::invtype::SHARED_BANK_SIZE,
RoF2::invtype::TRADE_SIZE, RoF2::invtype::WORLD_SIZE, RoF2::invtype::LIMBO_SIZE,
RoF2::invtype::TRIBUTE_SIZE, RoF2::invtype::TROPHY_TRIBUTE_SIZE, RoF2::invtype::GUILD_TRIBUTE_SIZE,
RoF2::invtype::MERCHANT_SIZE, RoF2::invtype::DELETED_SIZE, RoF2::invtype::CORPSE_SIZE,
RoF2::invtype::BAZAAR_SIZE, RoF2::invtype::INSPECT_SIZE, RoF2::invtype::REAL_ESTATE_SIZE,
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::invtype::ALT_STORAGE_SIZE, RoF2::invtype::ARCHIVED_SIZE,
RoF2::invtype::MAIL_SIZE, RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE, RoF2::invtype::KRONO_SIZE,
RoF2::invtype::OTHER_SIZE
),
RoF2::invslot::EQUIPMENT_BITMASK,
RoF2::invslot::GENERAL_BITMASK,
RoF2::invslot::CURSOR_BITMASK,
RoF2::invslot::POSSESSIONS_BITMASK,
RoF2::invslot::CORPSE_BITMASK,
RoF2::invbag::SLOT_COUNT,
RoF2::invaug::SOCKET_COUNT,
RoF2::inventory::AllowEmptyBagInBag,
RoF2::inventory::AllowClickCastFromBag,
RoF2::inventory::ConcatenateInvTypeLimbo,
RoF2::inventory::AllowOverLevelEquipment
),
/*[MobVersion::NPC] =*/
EQ::inventory::LookupEntry(
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
@@ -778,33 +743,6 @@ static const EQ::inventory::LookupEntry inventory_static_lookup_entries[EQ::vers
RoF2::invbag::SLOT_COUNT,
RoF2::invaug::SOCKET_COUNT,
false,
false,
false,
false
),
/*[MobVersion::OfflineLS] =*/
EQ::inventory::LookupEntry(
EQ::inventory::LookupEntry::InventoryTypeSize_Struct(
RoF2::INULL, RoF2::INULL, RoF2::INULL,
RoF2::invtype::TRADE_SIZE, RoF2::INULL, RoF2::INULL,
RoF2::INULL, RoF2::INULL, RoF2::INULL,
RoF2::invtype::MERCHANT_SIZE, RoF2::INULL, RoF2::INULL,
RoF2::invtype::BAZAAR_SIZE, RoF2::invtype::INSPECT_SIZE, RoF2::INULL,
RoF2::invtype::VIEW_MOD_PC_SIZE, RoF2::invtype::VIEW_MOD_BANK_SIZE, RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE,
RoF2::invtype::VIEW_MOD_LIMBO_SIZE, RoF2::INULL, RoF2::INULL,
RoF2::INULL, RoF2::INULL, RoF2::INULL,
RoF2::INULL
),
RoF2::INULL,
RoF2::INULL,
RoF2::INULL,
RoF2::INULL,
RoF2::INULL,
RoF2::invbag::SLOT_COUNT,
RoF2::invaug::SOCKET_COUNT,
false,
false,
false,
@@ -1056,10 +994,6 @@ static const EQ::behavior::LookupEntry behavior_static_lookup_entries[EQ::versio
EQ::behavior::LookupEntry(
RoF2::behavior::CoinHasWeight
),
/*[MobVersion::LS] =*/
EQ::behavior::LookupEntry(
RoF2::behavior::CoinHasWeight
),
/*[MobVersion::NPC] =*/
EQ::behavior::LookupEntry(
EQ::behavior::CoinHasWeight
@@ -1113,10 +1047,6 @@ static const EQ::behavior::LookupEntry behavior_static_lookup_entries[EQ::versio
RoF::behavior::CoinHasWeight
),
/*[MobVersion::OfflineRoF2] =*/
EQ::behavior::LookupEntry(
RoF2::behavior::CoinHasWeight
),
/*[MobVersion::OfflineLS] =*/
EQ::behavior::LookupEntry(
RoF2::behavior::CoinHasWeight
)
@@ -1272,19 +1202,6 @@ static const EQ::spells::LookupEntry spells_static_lookup_entries[EQ::versions::
RoF2::spells::NPC_BUFFS,
RoF2::spells::PET_BUFFS,
RoF2::spells::MERC_BUFFS
),
/*[ClientVersion::Laurion] =*/
EQ::spells::LookupEntry(
Laurion::spells::SPELL_ID_MAX,
Laurion::spells::SPELLBOOK_SIZE,
UF::spells::SPELL_GEM_COUNT, // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case
Laurion::spells::LONG_BUFFS,
Laurion::spells::SHORT_BUFFS,
Laurion::spells::DISC_BUFFS,
Laurion::spells::TOTAL_BUFFS,
Laurion::spells::NPC_BUFFS,
Laurion::spells::PET_BUFFS,
Laurion::spells::MERC_BUFFS
)
};
+1 -1
View File
@@ -29,7 +29,7 @@
#include "../common/patches/uf_limits.h"
#include "../common/patches/rof_limits.h"
#include "../common/patches/rof2_limits.h"
#include "../common/patches/laurion_limits.h"
namespace EQ
{
+32 -13
View File
@@ -47,13 +47,6 @@ static const uint32 ADVANCED_LORE_LENGTH = 8192;
*/
#pragma pack(1)
struct EqGuid
{
uint32_t Id;
uint16_t WorldId;
uint16_t Reserved;
};
struct LoginInfo_Struct {
/*000*/ char login_info[64];
/*064*/ uint8 unknown064[124];
@@ -331,7 +324,6 @@ union
bool guild_show;
bool trader;
bool buyer;
EqGuid CharacterGuid;
};
struct PlayerState_Struct {
@@ -4408,11 +4400,6 @@ struct FindPerson_Point {
float z;
};
struct FindPersonRequest_Struct {
uint32 npc_id;
FindPerson_Point client_pos;
};
//variable length packet of points
struct FindPersonResult_Struct {
FindPerson_Point dest;
@@ -6444,6 +6431,38 @@ struct BuylineItemDetails_Struct {
uint32 item_quantity;
};
/* Taken from libeq */
enum FindLocationType : uint32 {
LocationUnknown,
LocationPlayer,
LocationPOI,
LocationRealEstateItem,
LocationRealEstatePlot,
LocationMapPoint,
LocationSwitch,
LocationLocation
};
//For reference
struct FindableLocation_Struct {
/*00*/ FindLocationType type;
/*04*/ int32 id;
/*08*/ int32 sub_id;
/*12*/ int32 zone_id;
/*16*/ int32 zone_point_identifier;
/*20*/ float y;
/*24*/ float x;
/*28*/ float z;
/*32*/
};
struct FindPersonRequest_Struct {
FindLocationType type;
int32 id;
FindPerson_Point client_pos;
FindPerson_Point target_pos;
};
// Restore structure packing to default
#pragma pack()
File diff suppressed because it is too large Load Diff
-55
View File
@@ -1,55 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMMON_LAURION_H
#define COMMON_LAURION_H
#include "../struct_strategy.h"
class EQStreamIdentifier;
namespace Laurion
{
//these are the only public member of this namespace.
extern void Register(EQStreamIdentifier& into);
extern void Reload();
//you should not directly access anything below..
//I just dont feel like making a seperate header for it.
class Strategy : public StructStrategy {
public:
Strategy();
protected:
virtual std::string Describe() const;
virtual const EQ::versions::ClientVersion ClientVersion() const;
//magic macro to declare our opcode processors
#include "ss_declare.h"
#include "laurion_ops.h"
};
}; /*Laurion*/
#endif /*COMMON_LAURION_H*/
-284
View File
@@ -1,284 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "laurion_limits.h"
#include "../strings.h"
int16 Laurion::invtype::GetInvTypeSize(int16 inv_type)
{
switch (inv_type) {
case invtype::typePossessions:
return invtype::POSSESSIONS_SIZE;
case invtype::typeBank:
return invtype::BANK_SIZE;
case invtype::typeSharedBank:
return invtype::SHARED_BANK_SIZE;
case invtype::typeTrade:
return invtype::TRADE_SIZE;
case invtype::typeWorld:
return invtype::WORLD_SIZE;
case invtype::typeLimbo:
return invtype::LIMBO_SIZE;
case invtype::typeTribute:
return invtype::TRIBUTE_SIZE;
case invtype::typeTrophyTribute:
return invtype::TROPHY_TRIBUTE_SIZE;
case invtype::typeGuildTribute:
return invtype::GUILD_TRIBUTE_SIZE;
case invtype::typeMerchant:
return invtype::MERCHANT_SIZE;
case invtype::typeDeleted:
return invtype::DELETED_SIZE;
case invtype::typeCorpse:
return invtype::CORPSE_SIZE;
case invtype::typeBazaar:
return invtype::BAZAAR_SIZE;
case invtype::typeInspect:
return invtype::INSPECT_SIZE;
case invtype::typeRealEstate:
return invtype::REAL_ESTATE_SIZE;
case invtype::typeViewMODPC:
return invtype::VIEW_MOD_PC_SIZE;
case invtype::typeViewMODBank:
return invtype::VIEW_MOD_BANK_SIZE;
case invtype::typeViewMODSharedBank:
return invtype::VIEW_MOD_SHARED_BANK_SIZE;
case invtype::typeViewMODLimbo:
return invtype::VIEW_MOD_LIMBO_SIZE;
case invtype::typeAltStorage:
return invtype::ALT_STORAGE_SIZE;
case invtype::typeArchived:
return invtype::ARCHIVED_SIZE;
case invtype::typeMail:
return invtype::MAIL_SIZE;
case invtype::typeGuildTrophyTribute:
return invtype::GUILD_TROPHY_TRIBUTE_SIZE;
case invtype::typeKrono:
return invtype::KRONO_SIZE;
case invtype::typeOther:
return invtype::OTHER_SIZE;
default:
return INULL;
}
}
const char* Laurion::invtype::GetInvTypeName(int16 inv_type)
{
switch (inv_type) {
case invtype::TYPE_INVALID:
return "Invalid Type";
case invtype::typePossessions:
return "Possessions";
case invtype::typeBank:
return "Bank";
case invtype::typeSharedBank:
return "Shared Bank";
case invtype::typeTrade:
return "Trade";
case invtype::typeWorld:
return "World";
case invtype::typeLimbo:
return "Limbo";
case invtype::typeTribute:
return "Tribute";
case invtype::typeTrophyTribute:
return "Trophy Tribute";
case invtype::typeGuildTribute:
return "Guild Tribute";
case invtype::typeMerchant:
return "Merchant";
case invtype::typeDeleted:
return "Deleted";
case invtype::typeCorpse:
return "Corpse";
case invtype::typeBazaar:
return "Bazaar";
case invtype::typeInspect:
return "Inspect";
case invtype::typeRealEstate:
return "Real Estate";
case invtype::typeViewMODPC:
return "View MOD PC";
case invtype::typeViewMODBank:
return "View MOD Bank";
case invtype::typeViewMODSharedBank:
return "View MOD Shared Bank";
case invtype::typeViewMODLimbo:
return "View MOD Limbo";
case invtype::typeAltStorage:
return "Alt Storage";
case invtype::typeArchived:
return "Archived";
case invtype::typeMail:
return "Mail";
case invtype::typeGuildTrophyTribute:
return "Guild Trophy Tribute";
case invtype::typeKrono:
return "Krono";
case invtype::typeOther:
return "Other";
default:
return "Unknown Type";
}
}
bool Laurion::invtype::IsInvTypePersistent(int16 inv_type)
{
switch (inv_type) {
case invtype::typePossessions:
case invtype::typeBank:
case invtype::typeSharedBank:
case invtype::typeTrade:
case invtype::typeWorld:
case invtype::typeLimbo:
case invtype::typeTribute:
case invtype::typeTrophyTribute:
case invtype::typeGuildTribute:
return true;
default:
return false;
}
}
const char* Laurion::invslot::GetInvPossessionsSlotName(int16 inv_slot)
{
switch (inv_slot) {
case invslot::SLOT_INVALID:
return "Invalid Slot";
case invslot::slotCharm:
return "Charm";
case invslot::slotEar1:
return "Ear 1";
case invslot::slotHead:
return "Head";
case invslot::slotFace:
return "Face";
case invslot::slotEar2:
return "Ear 2";
case invslot::slotNeck:
return "Neck";
case invslot::slotShoulders:
return "Shoulders";
case invslot::slotArms:
return "Arms";
case invslot::slotBack:
return "Back";
case invslot::slotWrist1:
return "Wrist 1";
case invslot::slotWrist2:
return "Wrist 2";
case invslot::slotRange:
return "Range";
case invslot::slotHands:
return "Hands";
case invslot::slotPrimary:
return "Primary";
case invslot::slotSecondary:
return "Secondary";
case invslot::slotFinger1:
return "Finger 1";
case invslot::slotFinger2:
return "Finger 2";
case invslot::slotChest:
return "Chest";
case invslot::slotLegs:
return "Legs";
case invslot::slotFeet:
return "Feet";
case invslot::slotWaist:
return "Waist";
case invslot::slotPowerSource:
return "Power Source";
case invslot::slotAmmo:
return "Ammo";
case invslot::slotGeneral1:
return "General 1";
case invslot::slotGeneral2:
return "General 2";
case invslot::slotGeneral3:
return "General 3";
case invslot::slotGeneral4:
return "General 4";
case invslot::slotGeneral5:
return "General 5";
case invslot::slotGeneral6:
return "General 6";
case invslot::slotGeneral7:
return "General 7";
case invslot::slotGeneral8:
return "General 8";
case invslot::slotGeneral9:
return "General 9";
case invslot::slotGeneral10:
return "General 10";
case invslot::slotCursor:
return "Cursor";
default:
return "Unknown Slot";
}
}
const char* Laurion::invslot::GetInvSlotName(int16 inv_type, int16 inv_slot)
{
if (inv_type == invtype::typePossessions)
return invslot::GetInvPossessionsSlotName(inv_slot);
int16 type_size = invtype::GetInvTypeSize(inv_type);
if (!type_size || inv_slot == invslot::SLOT_INVALID)
return "Invalid Slot";
if ((inv_slot + 1) >= type_size)
return "Unknown Slot";
static std::string ret_str;
ret_str = StringFormat("Slot %i", (inv_slot + 1));
return ret_str.c_str();
}
const char* Laurion::invbag::GetInvBagIndexName(int16 bag_index)
{
if (bag_index == invbag::SLOT_INVALID)
return "Invalid Bag";
if (bag_index >= invbag::SLOT_COUNT)
return "Unknown Bag";
static std::string ret_str;
ret_str = StringFormat("Bag %i", (bag_index + 1));
return ret_str.c_str();
}
const char* Laurion::invaug::GetInvAugIndexName(int16 aug_index)
{
if (aug_index == invaug::SOCKET_INVALID)
return "Invalid Augment";
if (aug_index >= invaug::SOCKET_COUNT)
return "Unknown Augment";
static std::string ret_str;
ret_str = StringFormat("Augment %i", (aug_index + 1));
return ret_str.c_str();
}
-355
View File
@@ -1,355 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMMON_LAURION_LIMITS_H
#define COMMON_LAURION_LIMITS_H
#include "../types.h"
#include "../emu_versions.h"
#include "../skills.h"
namespace Laurion
{
const int16 IINVALID = -1;
const int16 INULL = 0;
namespace inventory {
inline EQ::versions::ClientVersion GetInventoryRef() { return EQ::versions::ClientVersion::Laurion; }
const bool ConcatenateInvTypeLimbo = false;
const bool AllowOverLevelEquipment = true;
const bool AllowEmptyBagInBag = true;
const bool AllowClickCastFromBag = true;
} /*inventory*/
namespace invtype {
inline EQ::versions::ClientVersion GetInvTypeRef() { return EQ::versions::ClientVersion::Laurion; }
namespace enum_ {
enum InventoryTypes : int16 {
typePossessions = INULL,
typeBank,
typeSharedBank,
typeTrade,
typeWorld,
typeLimbo,
typeTribute,
typeTrophyTribute,
typeGuildTribute,
typeMerchant,
typeDeleted,
typeCorpse,
typeBazaar,
typeInspect,
typeRealEstate,
typeViewMODPC,
typeViewMODBank,
typeViewMODSharedBank,
typeViewMODLimbo,
typeAltStorage,
typeArchived,
typeMail,
typeGuildTrophyTribute,
typeKrono,
typeOther,
typeMercenaryItems,
typeViewModMercenaryItems,
typeMountKeyRingItems,
typeViewModMountKeyRingItems,
typeIllusionKeyRingItems,
typeViewModIllusionKeyRingItems,
typeFamiliarKeyRingItems,
typeViewModFamiliarKeyRingItems,
typeHeroForgeKeyRingItems,
typeViewModHeroForgeKeyRingItems,
typeTeleportationKeyRingItems,
typeViewModTeleportationKeyRingItems,
typeOverflow,
typeDragonHoard,
typeTradeskillDepot,
typeGuildTradeskillDepot
};
} // namespace enum_
using namespace enum_;
const int16 POSSESSIONS_SIZE = 34;
const int16 BANK_SIZE = 24;
const int16 SHARED_BANK_SIZE = 2;
const int16 TRADE_SIZE = 8;
const int16 WORLD_SIZE = 10;
const int16 LIMBO_SIZE = 36;
const int16 TRIBUTE_SIZE = 5;
const int16 TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 GUILD_TRIBUTE_SIZE = 2;//unverified
const int16 MERCHANT_SIZE = 200;
const int16 DELETED_SIZE = 0;//unknown - "Recovery Tab"
const int16 CORPSE_SIZE = POSSESSIONS_SIZE;
const int16 BAZAAR_SIZE = 200;
const int16 INSPECT_SIZE = 23;
const int16 REAL_ESTATE_SIZE = 0;//unknown
const int16 VIEW_MOD_PC_SIZE = POSSESSIONS_SIZE;
const int16 VIEW_MOD_BANK_SIZE = BANK_SIZE;
const int16 VIEW_MOD_SHARED_BANK_SIZE = SHARED_BANK_SIZE;
const int16 VIEW_MOD_LIMBO_SIZE = LIMBO_SIZE;
const int16 ALT_STORAGE_SIZE = 0;//unknown - "Shroud Bank"
const int16 ARCHIVED_SIZE = 0;//unknown
const int16 MAIL_SIZE = 0;//unknown
const int16 GUILD_TROPHY_TRIBUTE_SIZE = 0;//unknown
const int16 KRONO_SIZE = 0;//unknown
const int16 OTHER_SIZE = 0;//unknown
const int16 TRADE_NPC_SIZE = 4; // defined by implication
const int16 TYPE_INVALID = IINVALID;
const int16 TYPE_BEGIN = typePossessions;
const int16 TYPE_END = typeOther;
const int16 TYPE_COUNT = (TYPE_END - TYPE_BEGIN) + 1;
int16 GetInvTypeSize(int16 inv_type);
const char* GetInvTypeName(int16 inv_type);
bool IsInvTypePersistent(int16 inv_type);
} /*invtype*/
namespace invslot {
inline EQ::versions::ClientVersion GetInvSlotRef() { return EQ::versions::ClientVersion::Laurion; }
namespace enum_ {
enum InventorySlots : int16 {
slotCharm = INULL,
slotEar1,
slotHead,
slotFace,
slotEar2,
slotNeck,
slotShoulders,
slotArms,
slotBack,
slotWrist1,
slotWrist2,
slotRange,
slotHands,
slotPrimary,
slotSecondary,
slotFinger1,
slotFinger2,
slotChest,
slotLegs,
slotFeet,
slotWaist,
slotPowerSource,
slotAmmo,
slotGeneral1,
slotGeneral2,
slotGeneral3,
slotGeneral4,
slotGeneral5,
slotGeneral6,
slotGeneral7,
slotGeneral8,
slotGeneral9,
slotGeneral10,
slotGeneral11,
slotGeneral12,
slotCursor
};
constexpr int16 format_as(InventorySlots slot) { return static_cast<int16>(slot); }
} // namespace enum_
using namespace enum_;
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 POSSESSIONS_BEGIN = slotCharm;
const int16 POSSESSIONS_END = slotCursor;
const int16 POSSESSIONS_COUNT = (POSSESSIONS_END - POSSESSIONS_BEGIN) + 1;
const int16 EQUIPMENT_BEGIN = slotCharm;
const int16 EQUIPMENT_END = slotAmmo;
const int16 EQUIPMENT_COUNT = (EQUIPMENT_END - EQUIPMENT_BEGIN) + 1;
//We support more if enabled but for now lets leave it at the 10 slots
const int16 GENERAL_BEGIN = slotGeneral1;
const int16 GENERAL_END = slotGeneral10;
const int16 GENERAL_COUNT = (GENERAL_END - GENERAL_BEGIN) + 1;
const int16 BONUS_BEGIN = invslot::slotCharm;
const int16 BONUS_STAT_END = invslot::slotPowerSource;
const int16 BONUS_SKILL_END = invslot::slotAmmo;
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor;
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
const uint64 GENERAL_BITMASK = 0x00000007FF800000;
const uint64 CURSOR_BITMASK = 0x0000000800000000;
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 36-slot count (Laurion+)
const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 36)); // based on 36-slot count (Laurion+)
const char* GetInvPossessionsSlotName(int16 inv_slot);
const char* GetInvSlotName(int16 inv_type, int16 inv_slot);
} /*invslot*/
namespace invbag {
inline EQ::versions::ClientVersion GetInvBagRef() { return EQ::versions::ClientVersion::Laurion; }
const int16 SLOT_INVALID = IINVALID;
const int16 SLOT_BEGIN = INULL;
const int16 SLOT_END = 9; //254;
const int16 SLOT_COUNT = 10; //255; // server Size will be 255..unsure what actual client is (test)
const char* GetInvBagIndexName(int16 bag_index);
} /*invbag*/
namespace invaug {
inline EQ::versions::ClientVersion GetInvAugRef() { return EQ::versions::ClientVersion::Laurion; }
const int16 SOCKET_INVALID = IINVALID;
const int16 SOCKET_BEGIN = INULL;
const int16 SOCKET_END = 5;
const int16 SOCKET_COUNT = 6;
const char* GetInvAugIndexName(int16 aug_index);
} /*invaug*/
namespace item {
inline EQ::versions::ClientVersion GetItemRef() { return EQ::versions::ClientVersion::Laurion; }
//enum Unknown : int { // looks like item class..but, RoF has it too - nothing in UF-
// Unknown1 = 0,
// Unknown2 = 1,
// Unknown3 = 2,
// Unknown4 = 5 // krono?
//};
enum ItemPacketType : int {
ItemPacketMerchant = 0x64,
ItemPacketTradeView = 0x65,
ItemPacketLoot = 0x66,
ItemPacketTrade = 0x67,
//looks like they added something at 0x68 that didn't exist before and shifted everything after it up by 1
ItemPacketUnknown068 = 0x68, //Not sure but it seems to deal with the cursor somehow.
ItemPacketCharInventory = 0x6A, //Rof 0x69 -> Larion 0x6a (requires translation)
ItemPacketLimbo = 0x6B, //0x6A -> 0x6B
ItemPacketWorldContainer = 0x6C,
ItemPacketTributeItem = 0x6D,
ItemPacketGuildTribute = 0x6E,
ItemPacketCharmUpdate = 0x6f,
ItemPacketRecovery = 0x72,
ItemPacketParcel = 0x74,
ItemPacketUnknown075 = 0x75, //Not sure but uses a lot of the same logic as the trade and char inventory types
ItemPacketOverflow = 0x76,
ItemPacketDragonHoard = 0x77,
ItemPacketTradeskill = 0x78,
ItemPacketTradeskillDepot = 0x79,
ItemPacketInvalid = 0xFF
};
} /*item*/
namespace profile {
inline EQ::versions::ClientVersion GetProfileRef() { return EQ::versions::ClientVersion::Laurion; }
const int16 BANDOLIERS_SIZE = 20; // number of bandolier instances
const int16 BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
const int16 POTION_BELT_SIZE = 5;
const int16 SKILL_ARRAY_SIZE = 100;
} /*profile*/
namespace constants {
inline EQ::versions::ClientVersion GetConstantsRef() { return EQ::versions::ClientVersion::Laurion; }
const EQ::expansions::Expansion EXPANSION = EQ::expansions::Expansion::LS;
const uint32 EXPANSION_BIT = EQ::expansions::bitLS;
const uint32 EXPANSIONS_MASK = EQ::expansions::maskLS;
const size_t CHARACTER_CREATION_LIMIT = 12;
const size_t SAY_LINK_BODY_SIZE = 56;
const uint32 MAX_GUILD_ID = 50000;
} /*constants*/
namespace behavior {
inline EQ::versions::ClientVersion GetBehaviorRef() { return EQ::versions::ClientVersion::Laurion; }
const bool CoinHasWeight = false;
} /*behavior*/
namespace skills {
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::Laurion; }
const size_t LastUsableSkill = EQ::skills::Skill2HPiercing;
} /*skills*/
namespace spells {
inline EQ::versions::ClientVersion GetSkillsRef() { return EQ::versions::ClientVersion::Laurion; }
enum class CastingSlot : uint32 {
Gem1 = 0,
Gem2 = 1,
Gem3 = 2,
Gem4 = 3,
Gem5 = 4,
Gem6 = 5,
Gem7 = 6,
Gem8 = 7,
Gem9 = 8,
Gem10 = 9,
Gem11 = 10,
Gem12 = 11,
MaxGems = 18, // fallacy..only 12 slot are useable...
Item = 12,
Discipline = 13,
AltAbility = 0xFF
};
const int SPELL_ID_MAX = 71999;
const int SPELLBOOK_SIZE = 1120;
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
const int SPELL_GEM_RECAST_TIMER = 15;
const int LONG_BUFFS = 42;
const int SHORT_BUFFS = 30;
const int DISC_BUFFS = 1;
const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS;
const int NPC_BUFFS = 400;
const int PET_BUFFS = NPC_BUFFS;
const int MERC_BUFFS = LONG_BUFFS;
} /*spells*/
}; /* Laurion */
#endif /*COMMON_LAURION_LIMITS_H*/
-96
View File
@@ -1,96 +0,0 @@
//list of packets we need to encode on the way out:
E(OP_Action)
E(OP_Animation)
E(OP_ApplyPoison)
E(OP_AugmentInfo)
E(OP_BeginCast)
E(OP_BlockedBuffs)
E(OP_Buff)
E(OP_BuffCreate)
E(OP_CancelTrade)
E(OP_CastSpell)
E(OP_ChannelMessage)
E(OP_CharInventory)
E(OP_ClickObjectAction)
E(OP_ClientUpdate)
E(OP_Consider)
E(OP_Damage)
E(OP_Death)
E(OP_DeleteCharge)
E(OP_DeleteItem)
E(OP_DeleteSpawn)
E(OP_DisciplineUpdate)
E(OP_ExpansionInfo)
E(OP_ExpUpdate)
E(OP_FormattedMessage)
E(OP_GMTraining)
E(OP_GMTrainSkillConfirm)
E(OP_GroundSpawn)
E(OP_HPUpdate)
E(OP_Illusion)
E(OP_ItemPacket)
E(OP_LogServer)
E(OP_ManaChange)
E(OP_MobHealth)
E(OP_MoneyOnCorpse)
E(OP_MoveItem)
E(OP_NewSpawn)
E(OP_NewZone)
E(OP_OnLevelMessage)
E(OP_PlayerProfile)
E(OP_RemoveBlockedBuffs)
E(OP_RespondAA)
E(OP_RequestClientZoneChange)
E(OP_RecipeAutoCombine)
E(OP_SendAATable)
E(OP_SendCharInfo)
E(OP_SendMaxCharacters)
E(OP_SendMembership)
E(OP_SendMembershipDetails)
E(OP_SendZonepoints)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SpecialMesg)
E(OP_SpawnAppearance)
E(OP_SpawnDoor)
E(OP_Stun)
E(OP_WearChange)
E(OP_ZoneChange)
E(OP_ZoneEntry)
E(OP_ZonePlayerToBind)
E(OP_ZoneSpawns)
//list of packets we need to decode on the way in:
D(OP_Animation)
D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BlockedBuffs)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_ClientUpdate)
D(OP_ClickDoor)
D(OP_Consider)
D(OP_ConsiderCorpse)
D(OP_DeleteItem)
D(OP_EnterWorld)
D(OP_GMTraining)
D(OP_GroupDisband)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_MoveItem)
D(OP_RemoveBlockedBuffs)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_SpawnAppearance)
D(OP_TradeSkillCombine)
D(OP_WearChange)
D(OP_ZoneEntry)
D(OP_ZoneChange)
#undef E
#undef D
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -26,7 +26,7 @@
#include "sod.h"
#include "rof.h"
#include "rof2.h"
#include "laurion.h"
void RegisterAllPatches(EQStreamIdentifier &into)
{
@@ -36,7 +36,6 @@ void RegisterAllPatches(EQStreamIdentifier &into)
UF::Register(into);
RoF::Register(into);
RoF2::Register(into);
Laurion::Register(into);
}
void ReloadAllPatches()
@@ -47,5 +46,4 @@ void ReloadAllPatches()
UF::Reload();
RoF::Reload();
RoF2::Reload();
Laurion::Reload();
}
+5 -1
View File
@@ -4538,10 +4538,14 @@ namespace RoF
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id);
IN(type)
IN(id);
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
IN(target_pos.x);
IN(target_pos.y);
IN(target_pos.z);
FINISH_DIRECT_DECODE();
}
+6 -32
View File
@@ -2680,7 +2680,7 @@ namespace RoF2
{
float instrument_mod = 0.0f;
uint8 effect_type = emu->buffs[r].effect_type;
uint32 player_id = emu->buffs[r].player_id;
uint32 player_id = emu->buffs[r].player_id;;
if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0)
{
@@ -3602,21 +3602,6 @@ namespace RoF2
FINISH_ENCODE();
}
ENCODE(OP_ShopRequest)
{
ENCODE_LENGTH_EXACT(MerchantClick_Struct);
SETUP_DIRECT_ENCODE(MerchantClick_Struct, structs::MerchantClick_Struct);
OUT(npc_id);
OUT(player_id);
OUT(command);
OUT(rate);
OUT(tab_display);
eq->unknown02 = emu->unknown020;
FINISH_ENCODE();
}
ENCODE(OP_SkillUpdate)
{
@@ -5532,10 +5517,14 @@ namespace RoF2
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id);
IN(type)
IN(id);
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
IN(target_pos.x);
IN(target_pos.y);
IN(target_pos.z);
FINISH_DIRECT_DECODE();
}
@@ -6008,21 +5997,6 @@ namespace RoF2
FINISH_DIRECT_DECODE();
}
DECODE(OP_ShopRequest)
{
DECODE_LENGTH_EXACT(structs::MerchantClick_Struct);
SETUP_DIRECT_DECODE(MerchantClick_Struct, structs::MerchantClick_Struct);
IN(npc_id);
IN(player_id);
IN(command);
IN(rate);
IN(tab_display);
emu->unknown020 = 0;
FINISH_DIRECT_DECODE();
}
DECODE(OP_Save)
{
DECODE_LENGTH_EXACT(structs::Save_Struct);
-2
View File
@@ -118,7 +118,6 @@ E(OP_SendZonepoints)
E(OP_SetGuildRank)
E(OP_ShopPlayerBuy)
E(OP_ShopPlayerSell)
E(OP_ShopRequest)
E(OP_SkillUpdate)
E(OP_SomeItemPacketMaybe)
E(OP_SpawnAppearance)
@@ -204,7 +203,6 @@ D(OP_Save)
D(OP_SetServerFilter)
D(OP_ShopPlayerBuy)
D(OP_ShopPlayerSell)
D(OP_ShopRequest)
D(OP_ShopSendParcel)
D(OP_Trader)
D(OP_TraderBuy)
+6 -7
View File
@@ -4016,14 +4016,13 @@ struct FindPerson_Point {
};
struct FindPersonRequest_Struct {
/*00*/ uint32 unknown00;
/*04*/ uint32 npc_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 unknown12;
/*00*/ FindLocationType type;
/*04*/ int32 id;
/*08*/ int32 unknown08;
/*12*/ int32 unknown12;
/*16*/ FindPerson_Point client_pos;
/*28*/ uint32 unknown28;
/*32*/ uint32 unknown32;
/*36*/ uint32 unknown36;
/*28*/ FindPerson_Point target_pos;
/*40*/
};
//variable length packet of points
+7 -8
View File
@@ -3779,14 +3779,13 @@ struct FindPerson_Point {
};
struct FindPersonRequest_Struct {
/*00*/ uint32 unknown00;
/*04*/ uint32 npc_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 unknown12;
/*16*/ FindPerson_Point client_pos;
/*28*/ uint32 unknown28;
/*32*/ uint32 unknown32;
/*36*/ uint32 unknown36;
/*00*/ FindLocationType type;
/*04*/ int32 id;
/*08*/ int32 unknown08;
/*12*/ int32 unknown12;
/*16*/ FindPerson_Point client_pos;
/*28*/ FindPerson_Point target_pos;
/*40*/
};
//variable length packet of points
+2 -1
View File
@@ -3150,7 +3150,8 @@ namespace SoD
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id);
emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
+2 -1
View File
@@ -2605,7 +2605,8 @@ namespace SoF
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id);
emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
+14
View File
@@ -3327,6 +3327,20 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_FindPersonRequest)
{
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
FINISH_DIRECT_DECODE();
}
// file scope helper methods
void SerializeItem(EQ::OutBuffer& ob, const EQ::ItemInstance *inst, int16 slot_id_in, uint8 depth) {
const char *protection = "\\\\\\\\\\";
+1
View File
@@ -132,6 +132,7 @@ D(OP_TradeSkillCombine)
D(OP_TributeItem)
D(OP_WearChange)
D(OP_WhoAllRequest)
D(OP_FindPersonRequest)
#undef E
#undef D
+2 -1
View File
@@ -3982,7 +3982,8 @@ namespace UF
DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct);
SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct);
IN(npc_id);
emu->type = FindLocationType::LocationPlayer;
emu->id = eq->npc_id;
IN(client_pos.x);
IN(client_pos.y);
IN(client_pos.z);
@@ -0,0 +1,547 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_FINDABLE_LOCATION_REPOSITORY_H
#define EQEMU_BASE_FINDABLE_LOCATION_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseFindableLocationRepository {
public:
struct FindableLocation {
uint32_t id;
std::string zone;
int32_t version;
int32_t findable_id;
int32_t findable_sub_id;
int32_t type;
int32_t zone_id;
int32_t zone_id_index;
float x;
float y;
float z;
int8_t min_expansion;
int8_t max_expansion;
std::string content_flags;
std::string content_flags_disabled;
};
static std::string PrimaryKey()
{
return std::string("id");
}
static std::vector<std::string> Columns()
{
return {
"id",
"zone",
"version",
"findable_id",
"findable_sub_id",
"type",
"zone_id",
"zone_id_index",
"x",
"y",
"z",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"zone",
"version",
"findable_id",
"findable_sub_id",
"type",
"zone_id",
"zone_id_index",
"x",
"y",
"z",
"min_expansion",
"max_expansion",
"content_flags",
"content_flags_disabled",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("findable_location");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static FindableLocation NewEntity()
{
FindableLocation e{};
e.id = 0;
e.zone = "";
e.version = 0;
e.findable_id = 0;
e.findable_sub_id = 0;
e.type = 0;
e.zone_id = 0;
e.zone_id_index = 0;
e.x = 0;
e.y = 0;
e.z = 0;
e.min_expansion = -1;
e.max_expansion = -1;
e.content_flags = "";
e.content_flags_disabled = "";
return e;
}
static FindableLocation GetFindableLocation(
const std::vector<FindableLocation> &findable_locations,
int findable_location_id
)
{
for (auto &findable_location : findable_locations) {
if (findable_location.id == findable_location_id) {
return findable_location;
}
}
return NewEntity();
}
static FindableLocation FindOne(
Database& db,
int findable_location_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
findable_location_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
FindableLocation e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.zone = row[1] ? row[1] : "";
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.findable_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.findable_sub_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.type = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.zone_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.zone_id_index = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.x = row[8] ? strtof(row[8], nullptr) : 0;
e.y = row[9] ? strtof(row[9], nullptr) : 0;
e.z = row[10] ? strtof(row[10], nullptr) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int findable_location_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
findable_location_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const FindableLocation &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[1] + " = '" + Strings::Escape(e.zone) + "'");
v.push_back(columns[2] + " = " + std::to_string(e.version));
v.push_back(columns[3] + " = " + std::to_string(e.findable_id));
v.push_back(columns[4] + " = " + std::to_string(e.findable_sub_id));
v.push_back(columns[5] + " = " + std::to_string(e.type));
v.push_back(columns[6] + " = " + std::to_string(e.zone_id));
v.push_back(columns[7] + " = " + std::to_string(e.zone_id_index));
v.push_back(columns[8] + " = " + std::to_string(e.x));
v.push_back(columns[9] + " = " + std::to_string(e.y));
v.push_back(columns[10] + " = " + std::to_string(e.z));
v.push_back(columns[11] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[12] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static FindableLocation InsertOne(
Database& db,
FindableLocation e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.id = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<FindableLocation> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<FindableLocation> All(Database& db)
{
std::vector<FindableLocation> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
FindableLocation e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.zone = row[1] ? row[1] : "";
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.findable_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.findable_sub_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.type = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.zone_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.zone_id_index = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.x = row[8] ? strtof(row[8], nullptr) : 0;
e.y = row[9] ? strtof(row[9], nullptr) : 0;
e.z = row[10] ? strtof(row[10], nullptr) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<FindableLocation> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<FindableLocation> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
FindableLocation e{};
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.zone = row[1] ? row[1] : "";
e.version = row[2] ? static_cast<int32_t>(atoi(row[2])) : 0;
e.findable_id = row[3] ? static_cast<int32_t>(atoi(row[3])) : 0;
e.findable_sub_id = row[4] ? static_cast<int32_t>(atoi(row[4])) : 0;
e.type = row[5] ? static_cast<int32_t>(atoi(row[5])) : 0;
e.zone_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : 0;
e.zone_id_index = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.x = row[8] ? strtof(row[8], nullptr) : 0;
e.y = row[9] ? strtof(row[9], nullptr) : 0;
e.z = row[10] ? strtof(row[10], nullptr) : 0;
e.min_expansion = row[11] ? static_cast<int8_t>(atoi(row[11])) : -1;
e.max_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const FindableLocation &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<FindableLocation> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.zone) + "'");
v.push_back(std::to_string(e.version));
v.push_back(std::to_string(e.findable_id));
v.push_back(std::to_string(e.findable_sub_id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.zone_id_index));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.min_expansion));
v.push_back(std::to_string(e.max_expansion));
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_FINDABLE_LOCATION_REPOSITORY_H
@@ -0,0 +1,50 @@
#ifndef EQEMU_FINDABLE_LOCATION_REPOSITORY_H
#define EQEMU_FINDABLE_LOCATION_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_findable_location_repository.h"
class FindableLocationRepository: public BaseFindableLocationRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* FindableLocationRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* FindableLocationRepository::GetWhereNeverExpires()
* FindableLocationRepository::GetWhereXAndY()
* FindableLocationRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_FINDABLE_LOCATION_REPOSITORY_H
-1
View File
@@ -340,7 +340,6 @@ RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be u
RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame")
RULE_BOOL(World, EnablePVPRegions, true, "Enables or disables PVP Regions automatically setting your PVP flag")
RULE_STRING(World, SupportedClients, "", "Comma-delimited list of clients to restrict to. Supported values are Titanium | SoF | SoD | UF | RoF | RoF2. Example: Titanium,RoF2")
RULE_INT(World, Id, 100, "Used by later clients to create GUIDs, expected to be Unique to the world but ultimately not that important")
RULE_CATEGORY_END()
RULE_CATEGORY(Zone)
+1
View File
@@ -282,6 +282,7 @@
#define ServerOP_ReloadBaseData 0x4128
#define ServerOP_ReloadSkillCaps 0x4129
#define ServerOP_ReloadNPCSpells 0x4130
#define ServerOP_ReloadFindableLocations 0x4131
#define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501
+3 -25
View File
@@ -573,13 +573,10 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
{
SerializeBuffer buf;
//from eqlsstr_us.txt id of each expansion, excluding 'Everquest'
int ExpansionLookup[30] = { 3007, 3008, 3009, 3010, 3012,
int ExpansionLookup[20] = { 3007, 3008, 3009, 3010, 3012,
3014, 3031, 3033, 3036, 3040,
3045, 3046, 3047, 3514, 3516,
3518, 3520, 3522, 3524, 3526,
3528, 3530, 3532, 3534, 3535,
3536, 3537, 3538, 3539, 3540
};
3518, 3520, 3522, 3524 };
if (server.options.IsDisplayExpansions()) {
@@ -587,26 +584,7 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
int32_t expansion = server.options.GetMaxExpansions();
int32_t owned_expansion = (expansion << 1) | 1;
if (m_client_version == cv_laurion) {
buf.WriteInt32(0x00);
buf.WriteInt32(0x00);
buf.WriteInt16(0x00);
buf.WriteInt32(30);
for (int i = 0; i < 30; i++)
{
buf.WriteUInt32(i + 1);
buf.WriteUInt8(1);
buf.WriteInt32(ExpansionLookup[i]);
buf.WriteInt32(6046);
buf.WriteUInt32(0xFFFFFFFF);
buf.WriteUInt32(0);
}
auto out = std::make_unique<EQApplicationPacket>(OP_LoginExpansionPacketData, buf);
m_connection->QueuePacket(out.get());
}
else if (m_client_version == cv_sod) {
if (m_client_version == cv_sod) {
// header info of packet. Requires OP_LoginExpansionPacketData=0x0031 to be in login_opcodes_sod.conf
buf.WriteInt32(0x00);
+14 -14
View File
@@ -56,7 +56,7 @@ void CheckSoDOpcodeFile(const std::string& path) {
}
}
void CheckLaurionOpcodeFile(const std::string& path) {
void CheckLarionOpcodeFile(const std::string& path) {
if (File::Exists(path)) {
return;
}
@@ -158,40 +158,40 @@ ClientManager::ClientManager()
}
);
int laurion_port = server.config.GetVariableInt("client_configuration", "laurion_port", 15900);
int larion_port = server.config.GetVariableInt("client_configuration", "larion_port", 15900);
EQStreamManagerInterfaceOptions laurion_opts(laurion_port, false, false);
EQStreamManagerInterfaceOptions larion_opts(larion_port, false, false);
laurion_stream = new EQ::Net::EQStreamManager(laurion_opts);
laurion_ops = new RegularOpcodeManager;
larion_stream = new EQ::Net::EQStreamManager(larion_opts);
larion_ops = new RegularOpcodeManager;
opcodes_path = fmt::format(
"{}/{}",
path.GetOpcodePath(),
"login_opcodes_laurion.conf"
"login_opcodes_larion.conf"
);
CheckLaurionOpcodeFile(opcodes_path);
CheckLarionOpcodeFile(opcodes_path);
if (!laurion_ops->LoadOpcodes(opcodes_path.c_str())) {
if (!larion_ops->LoadOpcodes(opcodes_path.c_str())) {
LogError(
"ClientManager fatal error: couldn't load opcodes for Laurion file [{0}]",
server.config.GetVariableString("client_configuration", "laurion_opcodes", "login_opcodes.conf")
"ClientManager fatal error: couldn't load opcodes for Larion file [{0}]",
server.config.GetVariableString("client_configuration", "larion_opcodes", "login_opcodes.conf")
);
run_server = false;
}
laurion_stream->OnNewConnection(
larion_stream->OnNewConnection(
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
LogInfo(
"New Laurion client connection from [{0}:{1}]",
"New Larion client connection from [{0}:{1}]",
long2ip(stream->GetRemoteIP()),
stream->GetRemotePort()
);
stream->SetOpcodeManager(&laurion_ops);
Client* c = new Client(stream, cv_laurion);
stream->SetOpcodeManager(&larion_ops);
Client* c = new Client(stream, cv_larion);
clients.push_back(c);
}
);
+2 -2
View File
@@ -55,8 +55,8 @@ private:
EQ::Net::EQStreamManager *titanium_stream;
OpcodeManager *sod_ops;
EQ::Net::EQStreamManager *sod_stream;
OpcodeManager *laurion_ops;
EQ::Net::EQStreamManager* laurion_stream;
OpcodeManager *larion_ops;
EQ::Net::EQStreamManager* larion_stream;
};
#endif
+1 -1
View File
@@ -84,7 +84,7 @@ struct PlayEverquestResponse_Struct {
enum LSClientVersion {
cv_titanium,
cv_sod,
cv_laurion
cv_larion
};
enum LSClientStatus {
+15 -58
View File
@@ -977,7 +977,8 @@ bool WorldServer::ValidateWorldServerAdminLogin(
return false;
}
void WorldServer::SerializeForClientServerListLegacy(class SerializeBuffer& out, bool use_local_ip) const {
void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const
{
// see LoginClientServerData_Struct
if (use_local_ip) {
out.WriteString(GetLocalIP());
@@ -986,6 +987,10 @@ void WorldServer::SerializeForClientServerListLegacy(class SerializeBuffer& out,
out.WriteString(GetRemoteIP());
}
if (version == cv_larion) {
out.WriteUInt32(9000);
}
switch (GetServerListID()) {
case LS::ServerType::Legends:
out.WriteInt32(LS::ServerTypeFlags::Legends);
@@ -997,8 +1002,15 @@ void WorldServer::SerializeForClientServerListLegacy(class SerializeBuffer& out,
out.WriteInt32(LS::ServerTypeFlags::Standard);
break;
}
out.WriteUInt32(GetServerId());
if (version == cv_larion) {
auto server_id = GetServerId();
//if this is 0, the client will not show the server in the list
out.WriteUInt32(1);
out.WriteUInt32(server_id);
}
else {
out.WriteUInt32(GetServerId());
}
out.WriteString(GetServerLongName());
out.WriteString("us"); // country code
@@ -1020,61 +1032,6 @@ void WorldServer::SerializeForClientServerListLegacy(class SerializeBuffer& out,
out.WriteUInt32(GetPlayersOnline());
}
void WorldServer::SerializeForClientServerListLaurion(class SerializeBuffer& out, bool use_local_ip) const {
if (use_local_ip) {
out.WriteString(GetLocalIP());
}
else {
out.WriteString(GetRemoteIP());
}
out.WriteUInt32(9000);
out.WriteUInt32(0);
uint32_t flags = 32; //all servers i saw had this set
switch (GetServerListID()) {
case LS::ServerType::Legends:
flags += LS::ServerTypeFlags::Legends;
break;
case LS::ServerType::Preferred:
flags += LS::ServerTypeFlags::Preferred;
break;
default:
flags += LS::ServerTypeFlags::Standard;
break;
}
out.WriteUInt32(flags);
out.WriteUInt32(GetServerId());
out.WriteString(GetServerLongName());
out.WriteString("EN");
out.WriteString("US");
if (GetStatus() < 0) {
if (GetZonesBooted() == 0) {
out.WriteInt32(LS::ServerStatusFlags::Down);
}
else {
out.WriteInt32(LS::ServerStatusFlags::Locked);
}
}
else {
out.WriteInt32(LS::ServerStatusFlags::Up);
}
out.WriteUInt32(GetPlayersOnline());
}
void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const
{
if (version == cv_laurion) {
SerializeForClientServerListLaurion(out, use_local_ip);
}
else {
SerializeForClientServerListLegacy(out, use_local_ip);
}
}
/**
* @param in_server_list_id
* @return
+1 -4
View File
@@ -149,10 +149,7 @@ public:
bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration);
bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration);
private:
void SerializeForClientServerListLegacy(class SerializeBuffer& out, bool use_local_ip) const;
void SerializeForClientServerListLaurion(class SerializeBuffer& out, bool use_local_ip) const;
public:
void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const;
private:
-699
View File
@@ -1,699 +0,0 @@
# ShowEQ Import Notes:
# ZERO THE FILE first
# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf
# Unknown Mapping:
# OP_Action2 -> OP_Damage
# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake
# Name Differences:
# OP_CancelInvite -> OP_GroupCancelInvite
# OP_GMFind -> OP_FindPersonRequest
# OP_CommonMessage -> OP_ChannelMessage
OP_Unknown=0x0000
OP_ExploreUnknown=0x0000 # used for unknown explorer
# world packets
# Required to reach Char Select:
OP_SendLoginInfo=0x2fca
OP_ApproveWorld=0x0000
OP_LogServer=0x6d4d
OP_SendCharInfo=0x832
OP_ExpansionInfo=0x066d
OP_EnterWorld=0x6691
OP_PostEnterWorld=0x2062
OP_World_Client_CRC1=0x74c8
OP_World_Client_CRC2=0x3984
OP_World_Client_CRC3=0x6516
OP_SendSpellChecksum=0x0000
OP_SendSkillCapsChecksum=0x0000
# Character Select Related:
OP_SendMaxCharacters=0x13af
OP_SendMembership=0x2aca
OP_SendMembershipDetails=0x2608
OP_CharacterCreateRequest=0x2df4
OP_CharacterCreate=0x6a3c
OP_DeleteCharacter=x67d7
OP_RandomNameGenerator=0x49d9
OP_ApproveName=0x11e5
OP_MOTD=0x0be4
OP_SetChatServer=0x0000
OP_SetChatServer2=0x2726
OP_ZoneServerInfo=0x2273
OP_WorldComplete=0x195c
OP_WorldUnknown001=0x2049
OP_FloatListThing=0x66fd
# Reasons for Disconnect:
OP_ZoneUnavail=0x582d
OP_WorldClientReady=0x7ed8
OP_CharacterStillInZone=0x0000
OP_WorldChecksumFailure=0x0000
OP_WorldLoginFailed=0x0000
OP_WorldLogout=0x0000
OP_WorldLevelTooHigh=0x0000
OP_CharInacessable=0x0000
OP_UserCompInfo=0x0000
OP_SendExeChecksum=0x0000
OP_SendBaseDataChecksum=0x0000
# Zone in opcodes
OP_AckPacket=0x77c9
OP_ZoneEntry=0x784a
OP_ReqNewZone=0x3895
OP_NewZone=0x4341
OP_ZoneSpawns=0x17d9
OP_PlayerProfile=0x1c76
OP_TimeOfDay=0x3736
OP_LevelUpdate=0x0eb2
OP_Stamina=0x1563
OP_RequestClientZoneChange=0x0191
OP_ZoneChange=0x17a3
OP_LockoutTimerInfo=0x0000
OP_ZoneServerReady=0x0000
OP_ZoneInUnknown=0x0000
OP_LogoutReply=0x0000
OP_PreLogoutReply=0x0000
# Required to fully log in
OP_SpawnAppearance=0x4eb0
OP_ChangeSize=0x2fdc
OP_Weather=0x6fe6
OP_ReqClientSpawn=0x6732
OP_SpawnDoor=0x4273
OP_GroundSpawn=0x49c5
OP_SendZonepoints=0x279f
OP_BlockedBuffs=0x4fdb
OP_RemoveBlockedBuffs=0x53cd
OP_ClearBlockedBuffs=0x5752
OP_WorldObjectsSent=0x2879
OP_SendExpZonein=0x02b4
OP_SendAATable=0x5f30
OP_ClearAA=0x3498
OP_ClearLeadershipAbilities=0x0000 #removed; leadership abilities are baked in and always on
OP_RespondAA=0x4c67
OP_UpdateAA=0x3b30
OP_SendAAStats=0x7d65 #i'll be honest i think this was removed at some point but this is the op at the spot in the list
OP_AAExpUpdate=0x642f #need to look into whether this has changed; exp did
OP_ExpUpdate=0x611d
OP_HPUpdate=0x775c
OP_ManaChange=0x700f
OP_TGB=0x0000 #removed; tgb is baked in and always on
OP_SpecialMesg=0x7d93
OP_CharInventory=0x21d6
OP_WearChange=0x44c0
OP_ClientUpdate=0x3a4b
OP_ClientReady=0x0831
OP_SetServerFilter=0x6b7f
# Guild Opcodes
OP_GuildsList=0x0000
OP_GuildMemberList=0x0000
OP_GuildMOTD=0x0000
OP_GetGuildMOTD=0x0000
OP_GetGuildMOTDReply=0x0000
OP_GuildMemberUpdate=0x0000
OP_GuildInvite=0x0000
OP_GuildRemove=0x0000
OP_GuildPeace=0x0000
OP_SetGuildMOTD=0x0000
OP_GuildWar=0x0000
OP_GuildLeader=0x0000
OP_GuildDelete=0x0000
OP_GuildInviteAccept=0x0000
OP_GuildDemote=0x0000
OP_GuildPromote=0x0000
OP_GuildPublicNote=0x0000
OP_GuildManageBanker=0x0000
OP_GuildBank=0x0000
OP_GuildBankItemList=0x0000
OP_SetGuildRank=0x0000
OP_GuildUpdate=0x0000
OP_GuildStatus=0x0000
OP_GuildCreate=0x0000
OP_GuildOpenGuildWindow=0x0000
OP_GuildMemberLevel=0x0000
OP_GuildMemberRankAltBanker=0x0000
OP_GuildMemberPublicNote=0x0000
OP_GuildMemberAdd=0x0000
OP_GuildMemberRename=0x0000
OP_GuildMemberDelete=0x0000
OP_GuildMemberDetails=0x0000
OP_GuildRenameGuild=0x0000
OP_LFGuild=0x0000
OP_GuildDeleteGuild=0x0000
# GM/Guide Opcodes
OP_GMServers=0x0000
OP_GMBecomeNPC=0x0000
OP_GMZoneRequest=0x0000
OP_GMZoneRequest2=0x0000
OP_GMGoto=0x0000
OP_GMSearchCorpse=0x0000
OP_GMHideMe=0x0000
OP_GMDelCorpse=0x0000
OP_GMApproval=0x0000
OP_GMToggle=0x0000
OP_GMSummon=0x0000
OP_GMEmoteZone=0x0000
OP_GMEmoteWorld=0x0000
OP_GMFind=0x0000
OP_GMKick=0x0000
OP_GMKill=0x0000
OP_GMNameChange=0x0000
OP_GMLastName=0x0000
# Misc Opcodes
OP_QueryUCSServerStatus=0x2570
OP_InspectRequest=0x0000
OP_InspectAnswer=0x0000
OP_InspectMessageUpdate=0x0000
OP_BeginCast=0x31f9
OP_ColoredText=0x0f3c
OP_ConsentResponse=0x3229
OP_MemorizeSpell=0x1d31
OP_LinkedReuse=0x7a8e
OP_SwapSpell=0x63c7
OP_CastSpell=0x325b
OP_Consider=0x53e3
OP_FormattedMessage=0x7f7f
OP_SimpleMessage=0x1943
OP_Buff=0x6ce5
OP_Illusion=0x5a3f
OP_MoneyOnCorpse=0x39d3
OP_RandomReply=0x6603
OP_DenyResponse=0x3f2c
OP_SkillUpdate=0x6735
OP_GMTrainSkillConfirm=0x6fbc
OP_RandomReq=0x528a
OP_Death=0x429a
OP_GMTraining=0x7c7a
OP_GMEndTraining=0x3ec6
OP_GMTrainSkill=0x54e1
OP_Animation=0x79c7
OP_Begging=0x7ded
OP_Consent=0x44fc
OP_ConsentDeny=0x3df9
OP_AutoFire=0x5280
OP_PetCommands=0x0000
OP_PetCommandState=0x0000
OP_PetHoTT=0x0000
OP_DeleteSpell=0x4281
OP_Surname=0x0000
OP_ClearSurname=0x0000
OP_FaceChange=0x0000
OP_SetFace=0x0000
OP_SenseHeading=0x6fcf
OP_Action=0x4c13
OP_ConsiderCorpse=0x6092
OP_HideCorpse=0x3f5c
OP_CorpseDrag=0x234d
OP_CorpseDrop=0x4342
OP_Bug=0x770b
OP_Feedback=0x0000
OP_Report=0x5bcf
OP_Damage=0x7d07
OP_ChannelMessage=0x6adc
OP_Assist=0x51f1
OP_AssistGroup=0x3f23
OP_MoveCoin=0x4e6a
OP_ZonePlayerToBind=0x5643
OP_KeyRing=0x0000
OP_WhoAllRequest=0x2a09
OP_WhoAllResponse=0x6404
OP_FriendsWho=0x75a2
OP_ConfirmDelete=0x4dd0
OP_Logout=0x771d
OP_Rewind=0x2b19
OP_TargetCommand=0x3b18
OP_Hide=0x1cdf
OP_Jump=0x6fa0
OP_Camp=0x326f
OP_Emote=0x0000
OP_SetRunMode=0x1449
OP_BankerChange=0x2a33
OP_TargetMouse=0x5741
OP_MobHealth=0x5b77
OP_InitialMobHealth=0x0000 # Unused?
OP_TargetHoTT=0x0000
OP_TargetBuffs=0x0000
OP_XTargetResponse=0x0000
OP_XTargetRequest=0x0000
OP_XTargetAutoAddHaters=0x0000
OP_XTargetOpen=0x0000
OP_XTargetOpenResponse=0x0000
OP_BuffCreate=0x27a1
OP_BuffRemoveRequest=0x4507
OP_DeleteSpawn=0x7712
OP_AutoAttack=0x3f03
OP_AutoAttack2=0x1c31
OP_Consume=0x5ef7
OP_MoveItem=0x11e3
OP_MoveMultipleItems=0x5205
OP_DeleteItem=0x0150
OP_DeleteCharge=0x1b7e
OP_ItemPacket=0x7d43
OP_ItemLinkResponse=0x0000
OP_ItemLinkClick=0x0000
OP_ItemPreview=0x0000
OP_NewSpawn=0x3ea8
OP_Track=0x5351
OP_TrackTarget=0x611a
OP_TrackUnknown=0x2c7a
OP_ClickDoor=0x733c
OP_MoveDoor=0x567c
OP_RemoveAllDoors=0x73e8
OP_EnvDamage=0x1ffd
OP_BoardBoat=0x7015
OP_LeaveBoat=0x2486
OP_ControlBoat=0x166f
OP_Forage=0x4c52
OP_SafeFallSuccess=0x6690
OP_RezzComplete=0x0000
OP_RezzRequest=0x0000
OP_RezzAnswer=0x0000
OP_Shielding=0x0000
OP_RequestDuel=0x0000
OP_MobRename=0x0000
OP_AugmentItem=0x3a1b
OP_WeaponEquip1=0x0000
OP_PlayerStateAdd=0x2178
OP_PlayerStateRemove=0x178e
OP_ApplyPoison=0x55b9
OP_Save=0x6da2
OP_TestBuff=0x0000
OP_CustomTitles=0x0000
OP_Split=0x7f6e
OP_YellForHelp=0x5fc9
OP_LoadSpellSet=0x0000
OP_Bandolier=0x0000
OP_PotionBelt=0x0000
OP_DuelDecline=0x0000
OP_DuelAccept=0x0000
OP_SaveOnZoneReq=0x3bfe
OP_ReadBook=0x51af
OP_Dye=0x0000
OP_InterruptCast=0x1d71
OP_AAAction=0x71BB
OP_LeadershipExpToggle=0x0000 #removed, these act as if all purchased now
OP_LeadershipExpUpdate=0x0000 #removed, these act as if all purchased now
OP_PurchaseLeadershipAA=0x0000 #removed, these act as if all purchased now
OP_UpdateLeadershipAA=0x0000 #removed, these act as if all purchased now
OP_MarkNPC=0x0000
OP_ClearNPCMarks=0x0000
OP_DelegateAbility=0x0000
OP_SetGroupTarget=0x0000
OP_Charm=0x66bb
OP_Stun=0x34be
OP_SendFindableNPCs=0x0000
OP_FindPersonRequest=0x0000
OP_FindPersonReply=0x0000
OP_Sound=0x2fa8
OP_CashReward=0x5e23
OP_PetBuffWindow=0x0000
OP_LevelAppearance=0x5d24
OP_Translocate=0x2772
OP_Sacrifice=0x2cbf
OP_PopupResponse=0x6be9
OP_OnLevelMessage=0x2a41
OP_AugmentInfo=0x2e11
OP_Petition=0x0000
OP_SomeItemPacketMaybe=0x0000
OP_PVPStats=0x0000
OP_PVPLeaderBoardRequest=0x0000
OP_PVPLeaderBoardReply=0x0000
OP_PVPLeaderBoardDetailsRequest=0x0000
OP_PVPLeaderBoardDetailsReply=0x0000
OP_RestState=0x0a92
OP_RespawnWindow=0x55ed
OP_LDoNButton=0x0000
OP_SetStartCity=0x0000
OP_VoiceMacroIn=0x703f
OP_VoiceMacroOut=0x72d1
OP_ItemViewUnknown=0x0000
OP_VetRewardsAvaliable=0x0000
OP_VetClaimRequest=0x0000
OP_VetClaimReply=0x0000
OP_DisciplineUpdate=0x6ce4
OP_DisciplineTimer=0x7436
OP_BecomeCorpse=0x0000 # Unused?
OP_Action2=0x0000 # Unused?
OP_MobUpdate=0x0000
OP_NPCMoveUpdate=0x0000
OP_CameraEffect=0x2f01
OP_SpellEffect=0x7378
OP_AddNimbusEffect=0x069f
OP_RemoveNimbusEffect=0x19ee
OP_AltCurrency=0x0000
OP_AltCurrencyMerchantRequest=0x0000
OP_AltCurrencyMerchantReply=0x0000
OP_AltCurrencyPurchase=0x0000
OP_AltCurrencySell=0x0000
OP_AltCurrencySellSelection=0x0000
OP_AltCurrencyReclaim=0x0000
OP_CrystalCountUpdate=0x0000
OP_CrystalCreate=0x0000
OP_CrystalReclaim=0x0000
OP_Untargetable=0x026f
OP_IncreaseStats=0x1005
OP_Weblink=0x16a3
OP_OpenContainer=0x6758
OP_Marquee=0x6bca
OP_ItemRecastDelay=0x547a
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
OP_ResetAA=0x53c0
OP_Fling=0x3731
OP_CancelSneakHide=0x7452
OP_AggroMeterLockTarget=0x0000
OP_AggroMeterTargetInfo=0x0000
OP_AggroMeterUpdate=0x0000
OP_UnderWorld=0x4ca9 # clients sends up when they detect an underworld issue, might be useful for cheat detection
OP_KickPlayers=0x7154
OP_BookButton=0x014d
# Expeditions
OP_DzQuit=0x0000
OP_DzListTimers=0x0000
OP_DzAddPlayer=0x0000
OP_DzRemovePlayer=0x0000
OP_DzSwapPlayer=0x0000
OP_DzMakeLeader=0x0000
OP_DzPlayerList=0x0000
OP_DzExpeditionInvite=0x0000
OP_DzExpeditionInviteResponse=0x0000
OP_DzExpeditionInfo=0x0000
OP_DzExpeditionLockoutTimers=0x0000
OP_DzMemberList=0x0000
OP_DzMemberListName=0x0000
OP_DzMemberListStatus=0x0000
OP_DzSetLeaderName=0x0000
OP_DzExpeditionEndsWarning=0x0000
OP_DzCompass=0x0000
OP_DzChooseZone=0x0000
OP_DzChooseZoneReply=0x0000
# New Opcodes
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
OP_ManaUpdate=0x0000
OP_EnduranceUpdate=0x0000
OP_MobManaUpdate=0x0000
OP_MobEnduranceUpdate=0x0000
# Mercenary Opcodes
OP_MercenaryDataUpdateRequest=0x0000
OP_MercenaryDataUpdate=0x0000
OP_MercenaryDataRequest=0x0000
OP_MercenaryDataResponse=0x0000
OP_MercenaryHire=0x0000
OP_MercenaryDismiss=0x0000
OP_MercenaryTimerRequest=0x0000
OP_MercenaryTimer=0x0000
OP_MercenaryUnknown1=0x0000
OP_MercenaryCommand=0x0000
OP_MercenarySuspendRequest=0x0000
OP_MercenarySuspendResponse=0x0000
OP_MercenaryUnsuspendResponse=0x0000
# Looting
OP_LootRequest=0x60e5
OP_EndLootRequest=0x35f6
OP_LootItem=0x0856
OP_LootComplete=0x1f5e
# bazaar trader stuff:
OP_BazaarSearch=0x0000
OP_TraderDelItem=0x0000
OP_BecomeTrader=0x0000
OP_TraderShop=0x0000
OP_TraderBulkSend=0x0000
OP_Trader=0x0000
OP_Barter=0x0000
OP_BuyerItems=0x0000
OP_TraderBuy=0x0000
OP_ShopItem=0x0000
OP_BazaarInspect=0x0000
OP_Bazaar=0x0000
OP_TraderItemUpdate=0x0000
# pc/npc trading
OP_TradeRequest=0x7066
OP_TradeAcceptClick=0x34ad
OP_TradeRequestAck=0x1c6b
OP_TradeCoins=0x44fe
OP_FinishTrade=0x0ec6
OP_CancelTrade=0x5839
OP_TradeMoneyUpdate=0x5fb3
OP_MoneyUpdate=0x70bb
OP_TradeBusy=0x109f
# Sent after canceling trade or after closing tradeskill object
OP_FinishWindow=0x50d4
OP_FinishWindow2=0x6b03
# Sent on Live for what seems to be item existance verification
# Ex. Before Right Click Effect happens from items
OP_ItemVerifyRequest=0x2003
OP_ItemVerifyReply=0x43d0
OP_ItemAdvancedLoreText=0x0000
# merchant stuff
OP_ShopPlayerSell=0x6489
OP_ShopRequest=0x840
OP_ShopEnd=0x74bb
OP_ShopEndConfirm=0x2ed1
OP_ShopPlayerBuy=0x625e
OP_ShopDelItem=0x4ce4
OP_ShopSendParcel=0x0f16
OP_ShopDeleteParcel=0x4e2a
OP_ShopRetrieveParcel=0x27d1
OP_ShopParcelIcon=0x4f27
# tradeskill stuff:
OP_ClickObject=0x687e
OP_ClickObjectAction=0x110f
OP_ClearObject=0x6155
OP_RecipeDetails=0x01e7
OP_RecipesFavorite=0x0495
OP_RecipesSearch=0x2f4e
OP_RecipeReply=0x2cd2
OP_RecipeAutoCombine=0x5dba
OP_TradeSkillCombine=0x4ed8
# Tribute Packets:
OP_TributeUpdate=0x0000
OP_TributeTimer=0x0000
OP_SendTributes=0x0000
OP_RequestGuildTributes=0x0000
OP_TributeInfo=0x0000
OP_OpenTributeMaster=0x0000
OP_SelectTribute=0x0000
OP_TributeItem=0x0000
OP_TributeMoney=0x0000
OP_TributeToggle=0x0000
OP_TributePointUpdate=0x0000
OP_TributeNPC=0x0000
OP_GuildTributeInfo=0x0000
OP_OpenTributeReply=0x0000
OP_GuildTributeStatus=0x0000
OP_GuildSaveActiveTributes=0x0000
OP_GuildSendActiveTributes=0x0000
OP_GuildTributeToggleReq=0x0000
OP_GuildTributeToggleReply=0x0000
OP_GuildTributeFavorAndTimer=0x0000
OP_GuildTributeDonateItem=0x0000
OP_GuildTributeDonatePlat=0x0000
OP_GuildSelectTribute=0x0000
OP_GuildModifyBenefits=0x0000
OP_GuildOptInOut=0x0000
OP_SendGuildTributes=0x0000
OP_OpenGuildTributeMaster=0x0000
# Adventure packets:
OP_LeaveAdventure=0x0000
OP_AdventureFinish=0x0000
OP_AdventureInfoRequest=0x0000
OP_AdventureInfo=0x0000
OP_AdventureRequest=0x0000
OP_AdventureDetails=0x0000
OP_AdventureData=0x0000
OP_AdventureUpdate=0x0000
OP_AdventureMerchantRequest=0x0000
OP_AdventureMerchantResponse=0x0000
OP_AdventureMerchantPurchase=0x0000
OP_AdventureMerchantSell=0x0000
OP_AdventurePointsUpdate=0x0000
OP_AdventureStatsRequest=0x0000
OP_AdventureStatsReply=0x0000
OP_AdventureLeaderboardRequest=0x0000
OP_AdventureLeaderboardReply=0x0000
# Group Opcodes
OP_GroupDisband=0x78ef
OP_GroupInvite=0x1d90
OP_GroupFollow=0x0000
OP_GroupUpdate=0x0000
OP_GroupUpdateB=0x0000
OP_GroupCancelInvite=0x0000
OP_GroupAcknowledge=0x0000
OP_GroupDelete=0x0000
OP_CancelInvite=0x0000
OP_GroupFollow2=0x0000
OP_GroupInvite2=0x1e7e
OP_GroupDisbandYou=0x0000
OP_GroupDisbandOther=0x0000
OP_GroupLeaderChange=0x0000
OP_GroupRoles=0x0000
OP_GroupMakeLeader=0x0000
OP_DoGroupLeadershipAbility=0x0000
OP_GroupLeadershipAAUpdate=0x0000 # removed these act as if you have always purchased them
OP_GroupMentor=0x0000
OP_InspectBuffs=0x0000
# LFG/LFP Opcodes
OP_LFGCommand=0x0000
OP_LFGGetMatchesRequest=0x0000
OP_LFGGetMatchesResponse=0x0000
OP_LFPGetMatchesRequest=0x0000
OP_LFPGetMatchesResponse=0x0000
OP_LFPCommand=0x0000
OP_LFGAppearance=0x0000
OP_LFGResponse=0x0000
# Raid Opcodes
OP_RaidInvite=0x0000
OP_RaidUpdate=0x0000
OP_RaidJoin=0x0000
OP_RaidDelegateAbility=0x0000
OP_MarkRaidNPC=0x0000
OP_RaidClearNPCMarks=0x0000
# Button-push commands
OP_Taunt=0x5064
OP_CombatAbility=0xbf
OP_SenseTraps=0x579c
OP_PickPocket=0x53d1
OP_DisarmTraps=0x21bf
OP_Disarm=0x31e9
OP_Sneak=0x78a7
OP_Fishing=0x57cc
OP_InstillDoubt=0x57cc
OP_FeignDeath=0x14b8
OP_Mend=0x6b8
OP_Bind_Wound=0x650e
OP_LDoNOpen=0x448
OP_LDoNPickLock=0x61c8
OP_LDoNInspect=0xc1c
# Task packets
OP_TaskDescription=0x0000
OP_TaskActivity=0x0000
OP_CompletedTasks=0x0000
OP_TaskActivityComplete=0x0000
OP_AcceptNewTask=0x0000
OP_CancelTask=0x0000
OP_AvaliableTask=0x0000
OP_TaskHistoryRequest=0x0000
OP_TaskHistoryReply=0x0000
OP_DeclineAllTasks=0x0000
OP_TaskRequestTimer=0x0000
OP_TaskSelectWindow=0x0000
# Shared Tasks
OP_SharedTaskMemberList=0x0000 #
OP_SharedTaskRemovePlayer=0x0000 # /taskremoveplayer
OP_SharedTaskAddPlayer=0x0000 # /taskaddplayer
OP_SharedTaskMakeLeader=0x0000 # /taskmakeleader
OP_SharedTaskInvite=0x0000 # Dialog window
OP_SharedTaskInviteResponse=0x0000 # Dialog window response
OP_SharedTaskAcceptNew=0x0000 #
OP_SharedTaskMemberChange=0x0000 #
OP_TaskTimers=0x0000 # /tasktimers
OP_SharedTaskQuit=0x0000 # /taskquit
OP_SharedTaskSelectWindow=0x0000
OP_SharedTaskPlayerList=0x0000 # /taskplayerlist
# Title opcodes
OP_NewTitlesAvailable=0x0000
OP_RequestTitles=0x0000
OP_SendTitleList=0x0000
OP_SetTitle=0x0000
OP_SetTitleReply=0x0000
# mail opcodes
OP_Command=0x0000
OP_MailboxHeader=0x0000
OP_MailHeader=0x0000
OP_MailBody=0x0000
OP_NewMail=0x0000
OP_SentConfirm=0x0000
########### Below this point should not be needed ###########
# This section are all unknown in Titanium
OP_ForceFindPerson=0x0000
OP_LocInfo=0x0000
OP_ReloadUI=0x0000
OP_ItemName=0x0000
OP_ItemLinkText=0x0000
OP_MultiLineMsg=0x0000
OP_MendHPUpdate=0x0000
OP_TargetReject=0x0000
OP_SafePoint=0x0000
OP_ApproveZone=0x0000
OP_ZoneComplete=0x0000
OP_ClientError=0x0000
OP_DumpName=0x0000
OP_Heartbeat=0x0000
OP_CrashDump=0x0000
OP_LoginComplete=0x0000
# discovered opcodes not yet used:
OP_PickLockSuccess=0x0000
OP_PlayMP3=0x6451
OP_ReclaimCrystals=0x0000
OP_DynamicWall=0x0000
OP_OpenDiscordMerchant=0x0000
OP_DiscordMerchantInventory=0x0000
OP_GiveMoney=0x0000
OP_RequestKnowledgeBase=0x0000
OP_KnowledgeBase=0x0000
OP_SlashAdventure=0x0000 # /adventure
OP_BecomePVPPrompt=0x0000
OP_MoveLogRequest=0x0000 # gone I think
OP_MoveLogDisregard=0x0000 # gone I think
# named unknowns, to make looking for real unknown easier
OP_AnnoyingZoneUnknown=0x0000
OP_Some6ByteHPUpdate=0x0000 #seems to happen when you target group members
OP_QueryResponseThing=0x0000
# realityincarnate: these are just here to stop annoying several thousand byte packet dumps
#OP_LoginUnknown1=0x0000 # OP_SendSpellChecksum
#OP_LoginUnknown2=0x0000 # OP_SendSkillCapsChecksum
# Petition Opcodes
OP_PetitionSearch=0x0000 #search term for petition
OP_PetitionSearchResults=0x0000 #(list of?) matches from search
OP_PetitionSearchText=0x0000 #text results of search
OP_PetitionUpdate=0x0000
OP_PetitionCheckout=0x0000
OP_PetitionCheckIn=0x0000
OP_PetitionQue=0x0000
OP_PetitionUnCheckout=0x0000
OP_PetitionDelete=0x0000
OP_DeletePetition=0x0000
OP_PetitionResolve=0x0000
OP_PDeletePetition=0x0000
OP_PetitionBug=0x0000
OP_PetitionRefresh=0x0000
OP_PetitionCheckout2=0x0000
OP_PetitionViewPetition=0x0000
#aura related
OP_UpdateAura=0x0000
OP_RemoveTrap=0x0000
OP_Fingerprint=0x7a5b
+1
View File
@@ -311,6 +311,7 @@ OP_SetGroupTarget=0x2814
OP_Charm=0x5d92
OP_Stun=0x36a4
OP_SendFindableNPCs=0x4613
OP_SendFindableLocations=0x6a68
OP_FindPersonRequest=0x5cea
OP_FindPersonReply=0x7e58
OP_Sound=0x1a30
+33
View File
@@ -0,0 +1,33 @@
CREATE TABLE `findable_location` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`zone` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_general_ci',
`version` INT(11) NOT NULL DEFAULT '0',
`findable_id` INT(11) NOT NULL DEFAULT '0',
`findable_sub_id` INT(11) NOT NULL DEFAULT '0',
`type` INT(11) NOT NULL DEFAULT '0',
`zone_id` INT(11) NOT NULL DEFAULT '0',
`zone_id_index` INT(11) NOT NULL DEFAULT '0',
`x` FLOAT NOT NULL DEFAULT '0',
`y` FLOAT NOT NULL DEFAULT '0',
`z` FLOAT NOT NULL DEFAULT '0',
`min_expansion` TINYINT(4) NOT NULL DEFAULT '-1',
`max_expansion` TINYINT(4) NOT NULL DEFAULT '-1',
`content_flags` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`content_flags_disabled` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `zone_version` (`zone`, `version`) USING BTREE
);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 77, -1, 6, 202, 0, 484.484130859375, 183.69752502441406, 0.0020000000949949026);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 16, 0, 7, 45, 1, 342.86285400390625, 188.9244384765625, -181.92721557617188);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 17, 0, 7, 1, 1, -6.997137069702148, -174.92999267578125, 15.993850708007812);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 18, 0, 7, 1, 2, 356.8572692871094, -48.98040771484375, 15.993560791015625);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 19, 0, 7, 4, 1, 566.7733154296875, 1699.3203125, 54.97816467285156);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 19, 2, 7, 4, 2, 230.90762329101562, 1699.3203125, 59.97674560546875);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 20, 0, 7, 4, 3, 141.9432373046875, 1699.3203125, 20.986679077148438);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 21, 0, 7, 4, 4, -3.9984021186828613, 1699.3203125, 20.986663818359375);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 21, 3, 7, 4, 5, -333.866455078125, 1699.3203125, 59.97560119628906);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 22, 0, 7, 4, 6, 899.6401977539062, 1699.3203125, 54.97816467285156);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 23, 0, 7, 4, 7, -799.6800537109375, 1699.3203125, 54.97825622558594);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 53, 0, 7, 45, 2, 76.9692153930664, 174.9300537109375, -34.986000061035156);
INSERT INTO `findable_location` (zone, version, findable_id, findable_sub_id, type, zone_id, zone_id_index, x, y, z) VALUES ('qeynos2', 0, 54, 0, 7, 45, 3, -160.9356231689453, 300.879638671875, -139.94403076171875);
-388
View File
@@ -1,388 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Nuget personal access tokens and Credentials
nuget.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
.idea/
*.sln.iml
@@ -1,621 +0,0 @@
using Ionic.Zlib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace StreamParser.Common.Daybreak
{
public class Connection : IConnection
{
private class EncodeType
{
public const int None = 0;
public const int Compression = 1;
public const int XOR = 4;
}
private enum SequenceOrder
{
Past,
Current,
Future
}
private readonly IParser _owner;
private readonly IPAddress _srcAddr;
private readonly int _srcPort;
private readonly IPAddress _dstAddr;
private readonly int _dstPort;
private readonly Util.Crc32 _crc_generator = new Util.Crc32();
private readonly Guid _id = Guid.NewGuid();
private uint _connect_code = 0;
private int _encode_key = 0;
private int _crc_bytes = 0;
private int[] _encode_pass = new int[2] { 0, 0 };
private ConnectionStream[] _client_streams = new ConnectionStream[4] {
new ConnectionStream(),
new ConnectionStream(),
new ConnectionStream(),
new ConnectionStream()
};
private ConnectionStream[] _server_streams = new ConnectionStream[4] {
new ConnectionStream(),
new ConnectionStream(),
new ConnectionStream(),
new ConnectionStream()
};
public IConnection.OnPacketRecvHandler OnPacketRecv { get; set; }
public IPAddress ClientAddress => _srcAddr;
public int ClientPort => _srcPort;
public IPAddress ServerAddress => _dstAddr;
public int ServerPort => _dstPort;
public Guid Id => _id;
public ConnectionType ConnectionType {
get
{
//World servers used to be coded to always be 9000 but live started using dynamic ports
//I've seen from 9000 to 9008 on live
if (_dstPort >= 9000 && _dstPort <= 9010)
{
return ConnectionType.World;
}
else if (_encode_pass[0] == EncodeType.None && _encode_pass[1] == EncodeType.None)
{
return ConnectionType.Login;
}
else if (_encode_pass[0] == EncodeType.XOR && _encode_pass[1] == EncodeType.None)
{
return ConnectionType.Chat;
}
else if (_encode_pass[0] == EncodeType.Compression && _encode_pass[1] == EncodeType.None)
{
return ConnectionType.Zone;
}
return ConnectionType.Unknown;
}
}
public Connection(IParser owner, IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort)
{
_owner = owner;
_srcAddr = srcAddr;
_srcPort = srcPort;
_dstAddr = dstAddr;
_dstPort = dstPort;
}
public void ProcessPacket(IPAddress srcAddr, int srcPort, DateTime packetTime, ReadOnlySpan<byte> data)
{
if (data.Length < 1)
{
return;
}
var opcode = data[1];
if (data[0] == 0 && (opcode == Opcode.KeepAlive || opcode == Opcode.OutboundPing))
{
return;
}
if (PacketCanBeDecoded(data))
{
if (!ValidateCRC(data))
{
return;
}
if (_encode_pass[0] == EncodeType.None && _encode_pass[1] == EncodeType.None)
{
ProcessDecodedPacket(srcAddr, srcPort, packetTime, data.Slice(0, data.Length - _crc_bytes));
}
else
{
//unfortunately we can't avoid a copy here
var temp = data.Slice(0, data.Length - _crc_bytes).ToArray();
for (int i = 1; i >= 0; --i)
{
switch(_encode_pass[i])
{
case EncodeType.Compression:
if(temp[0] == 0)
{
temp = Decompress(temp, 2, temp.Length - 2);
}
else
{
temp = Decompress(temp, 1, temp.Length - 1);
}
break;
case EncodeType.XOR:
if (temp[0] == 0)
{
temp = Decode(temp, 2, temp.Length - 2);
}
else
{
temp = Decode(temp, 1, temp.Length - 1);
}
break;
}
}
ProcessDecodedPacket(srcAddr, srcPort, packetTime, temp);
}
}
else
{
ProcessDecodedPacket(srcAddr, srcPort, packetTime, data);
}
}
private void ProcessDecodedPacket(IPAddress srcAddr, int srcPort, DateTime packetTime, ReadOnlySpan<byte> data)
{
if (data.Length < 1)
{
return;
}
if (data[0] == 0)
{
if (data.Length < 2)
{
return;
}
var opcode = data[1];
switch (opcode)
{
case Opcode.SessionResponse:
if (_connect_code == 0)
{
//if(data.Length != 21)
//{
// return;
//}
_connect_code = BitConverter.ToUInt32(data.Slice(2, 4));
_encode_key = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.Slice(6, 4)));
_crc_bytes = data[10];
_encode_pass[0] = data[11];
_encode_pass[1] = data[12];
_owner.OnNewConnection?.Invoke(this, packetTime);
}
break;
case Opcode.SessionDisconnect:
if(_connect_code != 0)
{
_connect_code = 0;
_encode_key = 0;
_crc_bytes = 0;
_encode_pass[0] = 0;
_encode_pass[1] = 0;
_owner.OnLostConnection?.Invoke(this, packetTime);
}
break;
case Opcode.Combined:
{
int current = 2;
int end = data.Length;
while (current < end)
{
byte subpacket_length = data[current];
current += 1;
if (end < current + subpacket_length)
{
return;
}
var subpacket = data.Slice(current, subpacket_length);
ProcessDecodedPacket(srcAddr, srcPort, packetTime, subpacket);
current += subpacket_length;
}
}
break;
case Opcode.AppCombined:
{
int current = 2;
int end = data.Length;
while (current < end)
{
int subpacket_length = 0;
if (data[current] == 0xff)
{
if (end < current + 3)
{
return;
}
if (data[current + 1] == 0xff && data[current + 2] == 0xff)
{
if (end < current + 7)
{
return;
}
subpacket_length =
((data[current + 3]) << 24) |
((data[current + 4]) << 16) |
((data[current + 5]) << 8) |
(data[current + 6]);
current += 7;
}
else
{
subpacket_length =
((data[current + 1]) << 8) |
(data[current + 2]);
current += 3;
}
}
else
{
subpacket_length = data[current];
current += 1;
}
var subpacket = data.Slice(current, subpacket_length);
ProcessDecodedPacket(srcAddr, srcPort, packetTime, subpacket);
current += subpacket_length;
}
}
break;
case Opcode.Packet:
case Opcode.Packet2:
case Opcode.Packet3:
case Opcode.Packet4:
{
var stream_id = opcode - Opcode.Packet;
var stream = FindStream(srcAddr, srcPort, stream_id);
var sequence = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data.Slice(2, 2)));
var order = CompareSequence(stream.Sequence, sequence);
if (order == SequenceOrder.Future)
{
if (!stream.PacketQueue.ContainsKey(sequence))
{
stream.PacketQueue.Add(sequence, new ConnectionStream.QueuedPacket
{
Data = data.ToArray(),
PacketTime = packetTime
});
}
}
else if (order == SequenceOrder.Current)
{
if (stream.PacketQueue.ContainsKey(sequence))
{
stream.PacketQueue.Remove(sequence);
}
stream.Sequence++;
ProcessDecodedPacket(srcAddr, srcPort, packetTime, data.Slice(4));
ProcessQueue(srcAddr, srcPort, stream_id);
}
}
break;
case Opcode.Fragment:
case Opcode.Fragment2:
case Opcode.Fragment3:
case Opcode.Fragment4:
{
var stream_id = opcode - Opcode.Fragment;
var stream = FindStream(srcAddr, srcPort, stream_id);
var sequence = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data.Slice(2, 2)));
var order = CompareSequence(stream.Sequence, sequence);
if (order == SequenceOrder.Future)
{
if (!stream.PacketQueue.ContainsKey(sequence))
{
stream.PacketQueue.Add(sequence, new ConnectionStream.QueuedPacket
{
Data = data.ToArray(),
PacketTime = packetTime
});
}
}
else if (order == SequenceOrder.Current)
{
if (stream.PacketQueue.ContainsKey(sequence))
{
stream.PacketQueue.Remove(sequence);
}
stream.Sequence++;
if (stream.TotalFragmentedBytes == 0)
{
stream.TotalFragmentedBytes = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.Slice(4, 4)));
stream.CurrentFragmentedBytes = (uint)(data.Length - 8);
if(stream.FragmentBuffer == null || stream.FragmentBuffer.Length < (stream.TotalFragmentedBytes + 512))
{
stream.FragmentBuffer = new byte[stream.TotalFragmentedBytes + 512];
}
var target = stream.FragmentBuffer.AsSpan();
data.Slice(8).CopyTo(target);
} else
{
var target = stream.FragmentBuffer.AsSpan((int)stream.CurrentFragmentedBytes);
data.Slice(4).CopyTo(target);
stream.CurrentFragmentedBytes += (uint)(data.Length - 4);
if (stream.CurrentFragmentedBytes >= stream.TotalFragmentedBytes)
{
ProcessDecodedPacket(srcAddr, srcPort, packetTime,
stream.FragmentBuffer.AsSpan(0, (int)stream.TotalFragmentedBytes));
stream.CurrentFragmentedBytes = 0;
stream.TotalFragmentedBytes = 0;
}
}
ProcessQueue(srcAddr, srcPort, stream_id);
}
}
break;
case Opcode.Padding:
OnPacketRecv?.Invoke(this, GetDirection(srcAddr, srcPort), packetTime, data.Slice(1));
break;
default:
break;
}
} else
{
OnPacketRecv?.Invoke(this, GetDirection(srcAddr, srcPort), packetTime, data);
}
}
private void ProcessQueue(IPAddress srcAddr, int srcPort, int stream_id)
{
var stream = FindStream(srcAddr, srcPort, stream_id);
var sequence = stream.Sequence;
//try to get the current sequence in the queue, if it exists then process it
ConnectionStream.QueuedPacket value;
if(stream.PacketQueue.TryGetValue(sequence, out value))
{
ProcessDecodedPacket(srcAddr, srcPort, value.PacketTime, value.Data);
}
}
public bool Match(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort)
{
var p1 = _srcAddr.Equals(srcAddr) && _srcPort == srcPort && _dstAddr.Equals(dstAddr) && _dstPort == dstPort;
var p2 = _srcAddr.Equals(dstAddr) && _srcPort == dstPort && _dstAddr.Equals(srcAddr) && _dstPort == srcPort;
return p1 || p2;
}
private SequenceOrder CompareSequence(ushort expected, ushort actual)
{
int diff = (int)actual - (int)expected;
if (diff == 0)
{
return SequenceOrder.Current;
}
if (diff > 0)
{
if (diff > 10000)
{
return SequenceOrder.Past;
}
return SequenceOrder.Future;
}
if (diff < -10000)
{
return SequenceOrder.Future;
}
return SequenceOrder.Past;
}
private bool PacketCanBeDecoded(ReadOnlySpan<byte> p)
{
if (p.Length < 2)
{
return false;
}
if (p[0] != 0)
{
return true;
}
var opcode = p[1];
if (opcode == Opcode.SessionRequest || opcode == Opcode.SessionResponse || opcode == Opcode.OutOfSession)
{
return false;
}
return true;
}
private bool ValidateCRC(ReadOnlySpan<byte> p)
{
try
{
if (_crc_bytes == 0)
{
return true;
}
int actual = 0;
int calculated = _crc_generator.Calculate(p.Slice(0, p.Length - _crc_bytes), _encode_key);
switch (_crc_bytes)
{
case 2:
actual = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(p.Slice(p.Length - 2, 2))) & 0xFFFF;
calculated = calculated & 0xFFFF;
break;
case 4:
actual = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(p.Slice(p.Length - 4, 4)));
break;
default:
return false;
}
return actual == calculated;
} catch(Exception ex)
{
return false;
}
}
private byte[] Decompress(byte[] p, int offset, int length)
{
if (length < 2)
{
return p;
}
Span<byte> header = p.AsSpan(0, offset);
byte flag = p[offset];
Span<byte> payload = p.AsSpan(offset + 1, length - 1);
if (flag == 0x5a)
{
var pl = payload.ToArray();
var inflated = Inflate(payload.ToArray());
byte[] ret = new byte[offset + inflated.Length];
Array.Copy(p, 0, ret, 0, offset);
Array.Copy(inflated, 0, ret, offset, inflated.Length);
return ret;
}
else if (flag == 0xa5)
{
byte[] ret = new byte[offset + length - 1];
Array.Copy(p, 0, ret, 0, offset);
Array.Copy(p, offset + 1, ret, offset, length - 1);
return ret;
}
else
{
return p;
}
}
private byte[] Inflate(byte[] p)
{
try
{
using (var out_stream = new MemoryStream())
{
using (var in_stream = new MemoryStream(p))
{
var buffer = new byte[512];
using (var zs = new ZlibStream(in_stream, CompressionMode.Decompress))
{
int r = 0;
do
{
r = zs.Read(buffer, 0, 512);
out_stream.Write(buffer, 0, r);
} while (r == 512);
}
}
var ret = out_stream.ToArray();
return ret;
}
}
catch (Exception)
{
return null;
}
}
private byte[] Decode(byte[] p, int offset, int length)
{
int key = _encode_key;
Span<byte> buffer = p.AsSpan(offset, length);
int i = 0;
for (i = 0; i + 4 <= length; i += 4)
{
int pt = BitConverter.ToInt32(buffer.Slice(i)) ^ key;
key = BitConverter.ToInt32(buffer.Slice(i));
if(BitConverter.TryWriteBytes(buffer.Slice(i), pt) == false)
{
throw new Exception("Error writing bytes back in decode.");
}
}
byte kc = (byte)(key & 0xFF);
for (; i < length; i++)
{
buffer[i] = (byte)(buffer[i] ^ kc);
}
return p;
}
private Direction GetDirection(IPAddress srcAddr, int srcPort)
{
if(srcAddr.Equals(_srcAddr) && srcPort == _srcPort)
{
return Direction.ClientToServer;
} else
{
return Direction.ServerToClient;
}
}
private ConnectionStream FindStream(IPAddress srcAddr, int srcPort, int index)
{
if (index < 0 || index > 3)
{
return null;
}
var dir = GetDirection(srcAddr, srcPort);
if(dir == Direction.ClientToServer)
{
return _client_streams[index];
} else
{
return _server_streams[index];
}
}
private class ConnectionStream
{
public class QueuedPacket
{
public byte[] Data { get; set; }
public DateTime PacketTime { get; set; }
}
public ConnectionStream()
{
Sequence = 0;
CurrentFragmentedBytes = 0;
TotalFragmentedBytes = 0;
FragmentBuffer = null;
PacketQueue = new Dictionary<ushort, QueuedPacket>();
}
public ushort Sequence { get; set; }
public uint CurrentFragmentedBytes { get; set; }
public uint TotalFragmentedBytes { get; set; }
public byte[] FragmentBuffer { get; set; }
public Dictionary<ushort, QueuedPacket> PacketQueue { get; set; }
}
}
}
@@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StreamParser.Common.Daybreak
{
public ref struct GamePacket
{
private readonly ReadOnlySpan<byte> _data;
public GamePacket(ReadOnlySpan<byte> data)
{
_data = data;
}
public readonly override string ToString()
{
return ToString(16);
}
public readonly string ToString(int columns)
{
int rows = _data.Length / columns;
if (_data.Length % columns != 0)
{
rows += 1;
}
int expected = (10 + columns * 4) * rows;
var sb = new StringBuilder(expected);
for(var i = 0; i < rows; ++i)
{
sb.AppendFormat("{0} |", (i * columns).ToString("X5"));
for(var j = 0; j < columns; ++j)
{
var index = (i * 16) + j;
if (index >= _data.Length)
{
sb.Append(" ");
} else
{
var c = _data[index];
sb.AppendFormat("{0,3}", c.ToString("X2"));
}
}
sb.Append(" | ");
for (var j = 0; j < columns; ++j)
{
var index = (i * 16) + j;
if (index >= _data.Length)
{
sb.Append(" ");
}
else
{
var c = _data[index];
var ch = (char)c;
if (char.IsLetterOrDigit(ch) || char.IsPunctuation(ch) || char.IsSymbol(ch) || (ch == ' '))
{
sb.Append(ch);
}
else
{
sb.Append(".");
}
}
}
sb.AppendLine();
}
return sb.ToString();
}
public readonly string ToModelString(int max_taken, bool hex)
{
int expected = Math.Min(_data.Length, max_taken) * (hex ? 2 : 1);
if(expected <= 0)
{
return string.Empty;
}
var sb = new StringBuilder(expected);
for(var i = 0; i < Math.Min(_data.Length, max_taken); ++i)
{
var c = _data[i];
if(hex)
{
sb.Append(c.ToString("X2"));
} else
{
var ch = (char)c;
if (char.IsLetterOrDigit(ch) || char.IsPunctuation(ch) || char.IsSymbol(ch) || (ch == ' '))
{
sb.Append(ch);
}
else
{
sb.Append(".");
}
}
}
return sb.ToString();
}
}
}
@@ -1,40 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace StreamParser.Common.Daybreak
{
public enum Direction
{
ClientToServer,
ServerToClient
}
public enum ConnectionType
{
Unknown,
Login,
World,
Chat,
Zone
}
public interface IConnection
{
delegate void OnPacketRecvHandler(Connection connection, Direction direction, DateTime packetTime, ReadOnlySpan<byte> data);
OnPacketRecvHandler OnPacketRecv { get; set; }
void ProcessPacket(IPAddress srcAddr, int srcPort, DateTime packetTime, ReadOnlySpan<byte> data);
bool Match(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort);
ConnectionType ConnectionType { get; }
IPAddress ClientAddress { get; }
int ClientPort { get; }
IPAddress ServerAddress { get; }
int ServerPort { get; }
Guid Id { get; }
}
}
@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StreamParser.Common.Daybreak
{
public interface IParser
{
delegate void ConnectionHandler(IConnection connection, DateTime connectionTime);
ConnectionHandler OnNewConnection { get; set; }
ConnectionHandler OnLostConnection { get; set; }
void Parse(string filename);
}
}
@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StreamParser.Common.Daybreak
{
public class Opcode
{
public const byte Padding = 0;
public const byte SessionRequest = 1;
public const byte SessionResponse = 2;
public const byte Combined = 3;
public const byte SessionDisconnect = 5;
public const byte KeepAlive = 6;
public const byte SessionStatRequest = 7;
public const byte SessionStatResponse = 8;
public const byte Packet = 9;
public const byte Packet2 = 10;
public const byte Packet3 = 11;
public const byte Packet4 = 12;
public const byte Fragment = 13;
public const byte Fragment2 = 14;
public const byte Fragment3 = 15;
public const byte Fragment4 = 16;
public const byte OutOfOrderAck = 17;
public const byte OutOfOrderAck2 = 18;
public const byte OutOfOrderAck3 = 19;
public const byte OutOfOrderAck4 = 20;
public const byte Ack = 21;
public const byte Ack2 = 22;
public const byte Ack3 = 23;
public const byte Ack4 = 22;
public const byte AppCombined = 25;
public const byte OutboundPing = 28;
public const byte OutOfSession = 29;
}
}
@@ -1,115 +0,0 @@
using Microsoft.Extensions.Logging;
using SharpPcap;
using SharpPcap.LibPcap;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace StreamParser.Common.Daybreak
{
public class Parser : IParser
{
/**
* Dependencies
*/
private readonly ILogger<Parser> _logger;
private readonly List<IConnection> _connections = new List<IConnection>();
public IParser.ConnectionHandler OnNewConnection { get; set; }
public IParser.ConnectionHandler OnLostConnection { get; set; }
public Parser(ILogger<Parser> logger)
{
_logger = logger;
}
public void Parse(string filename)
{
ICaptureDevice device = null;
try
{
device = new CaptureFileReaderDevice(filename);
device.Open();
device.OnPacketArrival += new PacketArrivalEventHandler(OnPacketCapture);
device.Capture();
device.Close();
} catch(Exception ex)
{
_logger.LogError(ex, "Error reading device capture.");
}
}
private void OnPacketCapture(object sender, PacketCapture capture)
{
var raw = capture.GetPacket();
if (raw.LinkLayerType == PacketDotNet.LinkLayers.Ethernet || raw.LinkLayerType == PacketDotNet.LinkLayers.Null)
{
var packet = PacketDotNet.Packet.ParsePacket(raw.LinkLayerType, raw.Data);
var ipPacket = packet.Extract<PacketDotNet.IPv4Packet>();
var udpPacket = packet.Extract<PacketDotNet.UdpPacket>();
if (ipPacket != null && udpPacket != null)
{
try
{
ProcessPacket(ipPacket.SourceAddress,
udpPacket.SourcePort,
ipPacket.DestinationAddress,
udpPacket.DestinationPort,
raw.Timeval.Date,
udpPacket.PayloadData);
} catch(Exception ex)
{
_logger.LogError(ex, "Error processing packet");
}
}
}
}
private void ProcessPacket(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort, DateTime packetTime, ReadOnlySpan<byte> data)
{
if(data.Length < 2)
{
_logger.LogTrace("Tossing packet, {0} was less than minimum packet size", data.Length);
return;
}
var c = FindConnection(srcAddr, srcPort, dstAddr, dstPort);
if(c != null)
{
c.ProcessPacket(srcAddr, srcPort, packetTime, data);
}
else if (data[0] == 0 && data[1] == Opcode.SessionRequest)
{
if(data.Length != 24)
{
_logger.LogTrace("Tossing packet, {0} was not the right size for a SessionRequest", data.Length);
return;
}
c = new Connection(this, srcAddr, srcPort, dstAddr, dstPort);
_connections.Add(c);
c.ProcessPacket(srcAddr, srcPort, packetTime, data);
}
}
private IConnection FindConnection(IPAddress srcAddr, int srcPort, IPAddress dstAddr, int dstPort)
{
foreach (var c in _connections)
{
if (c.Match(srcAddr, srcPort, dstAddr, dstPort))
{
return c;
}
}
return null;
}
}
}
-103
View File
@@ -1,103 +0,0 @@
using System;
namespace StreamParser.Common.Util
{
public class Crc32
{
private uint[] _encodeTable =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
public int Calculate(ReadOnlySpan<byte> data)
{
uint crc = 0xffffffff;
for (int i = 0; i < data.Length; ++i)
{
crc = ((crc >> 8) & 0x00FFFFFF) ^ _encodeTable[(crc ^ data[i]) & 0x000000FF];
}
return (int)~crc;
}
public int Calculate(ReadOnlySpan<byte> data, int key)
{
uint crc = 0xffffffff;
for (int i = 0; i < 4; ++i)
{
crc = ((crc >> 8) & 0x00FFFFFF) ^ _encodeTable[(crc ^ ((key >> (i * 8)) & 0xff)) & 0x000000FF];
}
for (int i = 0; i < data.Length; ++i)
{
crc = ((crc >> 8) & 0x00FFFFFF) ^ _encodeTable[(crc ^ data[i]) & 0x000000FF];
}
return (int)~crc;
}
}
}
-14
View File
@@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>StreamParser.Common</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Iconic.Zlib.Netstandard" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="SharpPcap" Version="6.3.0" />
</ItemGroup>
</Project>
-51
View File
@@ -1,51 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.6.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "stream_parser", "stream_parser\stream_parser.csproj", "{A5662497-4771-4A00-92E7-E7790CEB20E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "common", "common\common.csproj", "{FC625344-C003-4602-A571-D8811CF5B37A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x64.ActiveCfg = Debug|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x64.Build.0 = Debug|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Debug|x86.Build.0 = Debug|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|Any CPU.Build.0 = Release|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x64.ActiveCfg = Release|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x64.Build.0 = Release|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x86.ActiveCfg = Release|Any CPU
{A5662497-4771-4A00-92E7-E7790CEB20E9}.Release|x86.Build.0 = Release|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x64.ActiveCfg = Debug|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x64.Build.0 = Debug|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x86.ActiveCfg = Debug|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Debug|x86.Build.0 = Debug|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|Any CPU.Build.0 = Release|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x64.ActiveCfg = Release|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x64.Build.0 = Release|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x86.ActiveCfg = Release|Any CPU
{FC625344-C003-4602-A571-D8811CF5B37A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {89CDF826-F878-4BF4-8583-B9E66FE8B61D}
EndGlobalSection
EndGlobal
@@ -1,337 +0,0 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StreamParser.Common.Daybreak;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using CommandLine;
using System.Globalization;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Ionic.Zlib;
namespace StreamParser
{
public class ConsoleHostedService : IHostedService
{
private class ParsedPacket {
public byte[] Data { get; set; }
public Direction Direction { get; set; }
public DateTime Time { get; set; }
}
private class ParsedConnection
{
public IPAddress ClientAddress { get; set; }
public int ClientPort { get; set; }
public IPAddress ServerAddress { get; set; }
public int ServerPort { get; set; }
public ConnectionType ConnectionType { get; set; }
public List<ParsedPacket> Packets { get; set; }
public DateTime ConnectedTime { get; set; }
public DateTime? DisconnectedTime { get; set; }
}
private readonly ILogger<ConsoleHostedService> _logger;
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly IParser _parser;
private readonly Dictionary<Guid, ParsedConnection> _connections = new Dictionary<Guid, ParsedConnection>();
public ConsoleHostedService(ILogger<ConsoleHostedService> logger,
IHostApplicationLifetime applicationLifetime,
IParser parser)
{
_logger = logger;
_applicationLifetime = applicationLifetime;
_parser = parser;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_applicationLifetime.ApplicationStarted.Register(() =>
{
var args = Environment.GetCommandLineArgs();
try
{
CommandLine.Parser.Default.ParseArguments<ConsoleHostedServiceOptions>(args)
.WithParsed<ConsoleHostedServiceOptions>(o =>
{
_parser.OnNewConnection += OnNewConnection;
_parser.OnLostConnection += OnLostConnection;
foreach (var f in o.Input)
{
_logger.LogInformation("Parsing {0}...", f);
_parser.Parse(f);
}
foreach (var c in _connections)
{
if (c.Value.ConnectionType == ConnectionType.Unknown && !o.DumpUnknownStreams)
{
continue;
}
if (o.Text)
{
DumpConnectionToTextFile(c.Value, o.Output, o.Decrypt, o.DecompressOpcodes);
}
}
_applicationLifetime.StopApplication();
})
.WithNotParsed<ConsoleHostedServiceOptions>(e =>
{
bool stops_processing = false;
foreach (var err in e)
{
stops_processing = stops_processing || err.StopsProcessing || err is MissingRequiredOptionError;
}
if (stops_processing)
{
_applicationLifetime.StopApplication();
}
});
}
catch(Exception ex)
{
_logger.LogError(ex, "Error parsing command line arguments");
_applicationLifetime.StopApplication();
}
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private void OnNewConnection(IConnection connection, DateTime connectionTime)
{
_logger.LogTrace("New connection {0}:{1} <-> {2}:{3} of type {4}",
connection.ClientAddress,
connection.ClientPort,
connection.ServerAddress,
connection.ServerPort,
connection.ConnectionType);
connection.OnPacketRecv += OnPacketRecv;
_connections.Add(connection.Id, new ParsedConnection
{
ClientAddress = connection.ClientAddress,
ClientPort = connection.ClientPort,
ServerAddress = connection.ServerAddress,
ServerPort = connection.ServerPort,
ConnectionType = connection.ConnectionType,
Packets = new List<ParsedPacket>(),
ConnectedTime = connectionTime,
});
}
private void OnLostConnection(IConnection connection, DateTime connectionTime)
{
_logger.LogTrace("Lost connection {0}:{1} <-> {2}:{3}",
connection.ClientAddress,
connection.ClientPort,
connection.ServerAddress,
connection.ServerPort);
connection.OnPacketRecv -= OnPacketRecv;
var parsedConnection = _connections.GetValueOrDefault(connection.Id);
parsedConnection.DisconnectedTime = connectionTime;
}
private void OnPacketRecv(IConnection connection, Direction direction, DateTime packetTime, ReadOnlySpan<byte> data)
{
var parsedConnection = _connections.GetValueOrDefault(connection.Id);
parsedConnection.Packets.Add(new ParsedPacket
{
Data = data.ToArray(),
Direction = direction,
Time = packetTime
});
}
private void DumpConnectionToTextFile(ParsedConnection c, string output, bool decrypt, IEnumerable<int> decompressOpcodes)
{
try
{
var path = output + string.Format("{0}-{1}.txt", c.ConnectionType.ToString().ToLower(), c.ConnectedTime.ToString("yyyyMMddHHmmssfff"));
if (File.Exists(path))
{
File.Delete(path);
}
File.AppendAllText(path, string.Format("### type: {0}\n", c.ConnectionType));
File.AppendAllText(path, string.Format("### started: {0}\n", c.ConnectedTime.ToString("s")));
File.AppendAllText(path, string.Format("### ended: {0}\n", c.DisconnectedTime.HasValue ? c.DisconnectedTime.Value.ToString("s") : "unknown"));
File.AppendAllText(path, string.Format("### client: {0}:{1}\n", c.ClientAddress.ToString(), c.ClientPort));
File.AppendAllText(path, string.Format("### server: {0}:{1}\n\n", c.ServerAddress.ToString(), c.ServerPort));
foreach(var p in c.Packets)
{
ReadOnlySpan<byte> data = p.Data;
string dir = p.Direction == Direction.ClientToServer ? "Client -> Server" : "Server -> Client";
switch (c.ConnectionType)
{
case ConnectionType.Login:
{
int opcode = BitConverter.ToUInt16(data.Slice(0, 2));
{
File.AppendAllText(path,
string.Format("{0} [Opcode: 0x{1}, Size: {2}] ({3})\n", dir, opcode.ToString("X4"), data.Length - 2, p.Time.ToString("s")));
var gp = new GamePacket(data.Slice(2));
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
if(decrypt && opcode == 2 || opcode == 24)
{
var encrypted_block = data.Slice(12, data.Length - 12);
var dec = EQDecrypt(encrypted_block);
if(dec != null)
{
File.AppendAllText(path, string.Format("[Decrypted Data, Offset: {0}, Size: {1}]\n", 10, dec.Length));
gp = new GamePacket(dec);
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
}
}
}
}
break;
case ConnectionType.Chat:
{
int opcode = data[0];
File.AppendAllText(path,
string.Format("{0} [Opcode: 0x{1}, Size: {2}] ({3})\n", dir, opcode.ToString("X2"), data.Length - 1, p.Time.ToString("s")));
var gp = new GamePacket(data.Slice(1));
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
}
break;
default:
{
bool reported_decompressed = false;
int opcode = BitConverter.ToUInt16(data.Slice(0, 2));
foreach (var decompressOpcode in decompressOpcodes)
{
if (opcode == decompressOpcode && data.Length > 12)
{
if (data[10] == 0x78 && data[11] == 0xDA)
{
var totalLen = BitConverter.ToInt32(data.Slice(6, 4));
if (totalLen > 0)
{
var decompressed = Inflate(data.Slice(10));
if(decompressed != null)
{
var decompressed_gp = new GamePacket(decompressed);
File.AppendAllText(path,
string.Format("{0} [Opcode: 0x{1}, Size (decompressed): {2}] ({3})\n", dir, opcode.ToString("X4"), totalLen, p.Time.ToString("s")));
File.AppendAllText(path, string.Format("{0}\n", decompressed_gp.ToString()));
reported_decompressed = true;
break;
}
}
}
else if (data[6] == 0x78 && data[7] == 0xDA)
{
var totalLen = BitConverter.ToInt32(data.Slice(2, 4));
if (totalLen > 0)
{
var decompressed = Inflate(data.Slice(6));
if (decompressed != null)
{
File.AppendAllText(path,
string.Format("{0} [Opcode: 0x{1}, Size (decompressed): {2}] ({3})\n", dir, opcode.ToString("X4"), totalLen, p.Time.ToString("s")));
var decompressed_gp = new GamePacket(decompressed);
File.AppendAllText(path, string.Format("{0}\n", decompressed_gp.ToString()));
reported_decompressed = true;
break;
}
}
}
}
}
if (!reported_decompressed)
{
File.AppendAllText(path,
string.Format("{0} [Opcode: 0x{1}, Size: {2}] ({3})\n", dir, opcode.ToString("X4"), data.Length - 2, p.Time.ToString("s")));
var gp = new GamePacket(data.Slice(2));
File.AppendAllText(path, string.Format("{0}\n", gp.ToString()));
}
}
break;
}
}
}
catch(Exception ex)
{
_logger.LogError(ex, "Error dumping connection {0} to txt file", c.ConnectedTime.ToString("s"));
}
}
private byte[] Inflate(ReadOnlySpan<byte> data)
{
try
{
using (var out_stream = new MemoryStream())
using (var in_stream = new MemoryStream(data.ToArray()))
{
const int bufferLen = 4096;
var buffer = new byte[bufferLen];
using (var zs = new ZlibStream(in_stream, CompressionMode.Decompress))
{
int r = 0;
do
{
r = zs.Read(buffer, 0, bufferLen);
out_stream.Write(buffer, 0, r);
} while (r == bufferLen);
}
var ret = out_stream.ToArray();
return ret;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error inflating data");
return null;
}
}
private byte[] EQDecrypt(ReadOnlySpan<byte> data)
{
try
{
var desEngine = new DesEngine();
var cbcBlockCipher = new CbcBlockCipher(desEngine);
var bufferedBlockCipher = new BufferedBlockCipher(cbcBlockCipher);
bufferedBlockCipher.Init(false, new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8]));
var cipherData = new byte[bufferedBlockCipher.GetOutputSize(data.Length)];
var outputLength = bufferedBlockCipher.ProcessBytes(data.ToArray(), 0, data.Length, cipherData, 0);
bufferedBlockCipher.DoFinal(cipherData, outputLength);
return cipherData;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error decrypting EQ Datablock");
return null;
}
}
}
}
@@ -1,29 +0,0 @@
using System.Collections.Generic;
using CommandLine;
namespace StreamParser
{
public class ConsoleHostedServiceOptions
{
[Option("input", Required = true, HelpText = "Input pcap files to be processed.")]
public IEnumerable<string> Input { get; set; }
[Option("output", Default = "output/", HelpText = "Directory to put output files")]
public string Output { get; set; }
[Option("text", Default = true, HelpText = "Dump connections to text files.")]
public bool Text { get; set; }
[Option("binary", Default = false, HelpText = "Dump connections to binary files.")]
public bool Binary { get; set; }
[Option("decrypt", Default = false, HelpText = "Decrypt the \"Encrypted\" packets.")]
public bool Decrypt { get; set; }
[Option("decompress", Default = null, HelpText = "Which opcodes to attempt to decompress")]
public IEnumerable<int> DecompressOpcodes { get; set; }
[Option("enable-unknown-streams", Default = false, HelpText = "Enable dumping of unknown streams; they will be skipped otherwise.")]
public bool DumpUnknownStreams { get; set; }
}
}
@@ -1,25 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StreamParser.Common.Daybreak;
using System;
namespace StreamParser
{
class Program
{
static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddScoped<IParser, Parser>();
services.AddHostedService<ConsoleHostedService>();
});
}
}
}
@@ -1,9 +0,0 @@
{
"profiles": {
"stream_parser": {
"commandName": "Project",
"commandLineArgs": "--input input/cap_login_to_zone_10_16_2024.pcap --output output_test/ --binary --decrypt --decompress 16742 168 30346",
"workingDirectory": "E:\\Projects\\stream_parser\\stream_parser\\bin\\Debug\\net6.0\\"
}
}
}
@@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>StreamParser</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\common\common.csproj" />
</ItemGroup>
</Project>
+2 -5
View File
@@ -1209,11 +1209,8 @@ bool Client::Process() {
}
if(connect.Check()){
if (!(m_ClientVersionBit & EQ::versions::maskLaurionAndLater)) {
SendGuildList();// Send OPCode: OP_GuildsList
SendApproveWorld();
}
SendGuildList();// Send OPCode: OP_GuildsList
SendApproveWorld();
connect.Disable();
}
+1
View File
@@ -140,6 +140,7 @@ std::vector<Reload> reload_types = {
Reload{.command = "aa", .opcode = ServerOP_ReloadAAData, .desc = "Alternate Advancement"},
Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"},
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
Reload{.command = "finable_locations", .opcode = ServerOP_ReloadFindableLocations, .desc = "Findable Locations"},
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
Reload{.command = "content_flags", .opcode = ServerOP_ReloadContentFlags, .desc = "Content Flags"},
+1
View File
@@ -1401,6 +1401,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_ReloadAAData:
case ServerOP_ReloadAlternateCurrencies:
case ServerOP_ReloadBaseData:
case ServerOP_ReloadFindableLocations:
case ServerOP_ReloadBlockedSpells:
case ServerOP_ReloadCommands:
case ServerOP_ReloadDoors:
+1
View File
@@ -170,6 +170,7 @@ SET(zone_sources
zonedb.cpp
zone_base_data.cpp
zone_event_scheduler.cpp
zone_finable_locations.cpp
zone_npc_factions.cpp
zone_reload.cpp
zoning.cpp
+22 -71
View File
@@ -534,7 +534,7 @@ void Client::SendZoneInPackets()
if (GetLevel() >= 51)
SendAlternateAdvancementStats();
// Send exp packets
outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct));
ExpUpdate_Struct* eu = (ExpUpdate_Struct*)outapp->pBuffer;
uint32 tmpxp1 = GetEXPForLevel(GetLevel() + 1);
@@ -1168,7 +1168,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
}
}
if (message[0] == COMMAND_CHAR || message[0] == COMMAND_CHAR_NON_HASH) {
if (message[0] == COMMAND_CHAR) {
if (command_dispatch(this, message, false) == -2) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
@@ -7518,7 +7518,7 @@ void Client::GarbleMessage(char *message, uint8 variance)
int delimiter_count = 0;
// Don't garble # commands
if (message[0] == COMMAND_CHAR || message[0] == COMMAND_CHAR_NON_HASH || message[0] == BOT_COMMAND_CHAR) {
if (message[0] == COMMAND_CHAR || message[0] == BOT_COMMAND_CHAR) {
return;
}
@@ -8593,44 +8593,6 @@ void Client::SendHPUpdateMarquee(){
SendMarqueeMessage(Chat::Yellow, 510, 0, 3000, 3000, health_update_notification);
}
void Client::SendMembership() {
if (m_ClientVersion >= EQ::versions::ClientVersion::Laurion) {
auto outapp = new EQApplicationPacket(OP_SendMembership, sizeof(Membership_Struct));
Membership_Struct* mc = (Membership_Struct*)outapp->pBuffer;
mc->membership = 2; //Hardcode to gold for now. We don't use anything else.
mc->races = 0x1ffff; // Available Races (4110 for silver)
mc->classes = 0x1ffff; // Available Classes (4614 for silver) - Was 0x101ffff
mc->entrysize = 21; // Number of membership setting entries below
mc->entries[0] = 0xffffffff; // Max AA Restriction
mc->entries[1] = 0xffffffff; // Max Level Restriction
mc->entries[2] = 0xffffffff; // Max Char Slots per Account (not used by client?)
mc->entries[3] = 0xffffffff; // 1 for Silver
mc->entries[4] = 0xffffffff; // Main Inventory Size (0xffffffff on Live for Gold, but limiting to 8 until 10 is supported)
mc->entries[5] = 0xffffffff; // Max Platinum per level
mc->entries[6] = 1; // 0 for Silver
mc->entries[7] = 1; // 0 for Silver
mc->entries[8] = 1; // 1 for Silver
mc->entries[9] = 0xffffffff; // Unknown - Maybe Loyalty Points every 12 hours? 60 per week for Silver
mc->entries[10] = 1; // 1 for Silver
mc->entries[11] = 0xffffffff; // Shared Bank Slots
mc->entries[12] = 0xffffffff; // Unknown - Maybe Max Active Tasks?
mc->entries[13] = 1; // 1 for Silver
mc->entries[14] = 1; // 0 for Silver
mc->entries[15] = 1; // 0 for Silver
mc->entries[16] = 1; // 1 for Silver
mc->entries[17] = 1; // 0 for Silver
mc->entries[18] = 1; // 0 for Silver
mc->entries[19] = 0xffffffff; // 0 for Silver
mc->entries[20] = 0xffffffff; // 0 for Silver
mc->exit_url_length = 0;
//mc->exit_url = 0; // Used on Live: "http://www.everquest.com/free-to-play/exit-silver"
QueuePacket(outapp);
safe_delete(outapp);
}
}
uint32 Client::GetMoney(uint8 type, uint8 subtype) {
uint32 value = 0;
@@ -12033,15 +11995,13 @@ void Client::MaxSkills()
}
}
void Client::SendPath(Mob* target)
{
void Client::SendPath(Mob* target) {
if (!target) {
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
if (
!RuleB(Pathing, Find) &&
RuleB(Bazaar, EnableWarpToTrader) &&
@@ -12049,7 +12009,7 @@ void Client::SendPath(Mob* target)
(
target->CastToClient()->IsTrader() ||
target->CastToClient()->IsBuyer()
)
)
) {
Message(
Chat::Yellow,
@@ -12069,6 +12029,17 @@ void Client::SendPath(Mob* target)
return;
}
glm::vec3 target_loc(
target->GetX(),
target->GetY(),
target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION
);
SendPath(target_loc);
}
void Client::SendPath(const glm::vec3& loc)
{
std::vector<FindPerson_Point> points;
if (!RuleB(Pathing, Find) || !zone->pathing) {
@@ -12079,9 +12050,9 @@ void Client::SendPath(Mob* target)
a.x = GetX();
a.y = GetY();
a.z = GetZ();
b.x = target->GetX();
b.y = target->GetY();
b.z = target->GetZ();
b.x = loc.x;
b.y = loc.y;
b.z = loc.z;
points.push_back(a);
points.push_back(b);
@@ -12094,9 +12065,9 @@ void Client::SendPath(Mob* target)
);
glm::vec3 path_end(
target->GetX(),
target->GetY(),
target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION
loc.x,
loc.y,
loc.z
);
bool partial = false;
@@ -12119,18 +12090,6 @@ void Client::SendPath(Mob* target)
bool leads_to_teleporter = false;
auto v = path_list.back();
p.x = v.pos.x;
p.y = v.pos.y;
p.z = v.pos.z;
points.push_back(p);
p.x = GetX();
p.y = GetY();
p.z = GetZ();
points.push_back(p);
for (const auto &n: path_list) {
if (n.teleport) {
leads_to_teleporter = true;
@@ -12146,14 +12105,6 @@ void Client::SendPath(Mob* target)
++point_number;
}
if (!leads_to_teleporter) {
p.x = target->GetX();
p.y = target->GetY();
p.z = target->GetZ();
points.push_back(p);
}
}
SendPathPacket(points);
+1 -1
View File
@@ -869,6 +869,7 @@ public:
int GetAccountAge();
void SendPath(Mob* target);
void SendPath(const glm::vec3 &loc);
bool IsDiscovered(uint32 itemid);
void DiscoverItem(uint32 itemid);
@@ -1786,7 +1787,6 @@ public:
void ResetHPUpdateTimer() { hpupdate_timer.Start(); }
void SendHPUpdateMarquee();
void SendMembership();
void CheckRegionTypeChanges();
+61 -23
View File
@@ -118,6 +118,7 @@ void MapOpcodes()
ConnectingOpcodes[OP_ZoneEntry] = &Client::Handle_Connect_OP_ZoneEntry;
// connected opcode handler assignments:
ConnectedOpcodes[OP_0x0193] = &Client::Handle_0x0193;
ConnectedOpcodes[OP_AAAction] = &Client::Handle_OP_AAAction;
ConnectedOpcodes[OP_AcceptNewTask] = &Client::Handle_OP_AcceptNewTask;
ConnectedOpcodes[OP_AdventureInfoRequest] = &Client::Handle_OP_AdventureInfoRequest;
@@ -857,6 +858,9 @@ void Client::CompleteConnect()
if (ClientVersion() >= EQ::versions::ClientVersion::SoD)
entity_list.SendFindableNPCList(this);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF2)
zone->SendFindableLocations(this);
if (IsInAGuild()) {
if (firstlogon == 1) {
guild_mgr.UpdateDbMemberOnline(CharacterID(), true);
@@ -1202,6 +1206,10 @@ void Client::Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app)
void Client::Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app)
{
auto outapp = new EQApplicationPacket(OP_0x0347, 0);
QueuePacket(outapp);
safe_delete(outapp);
return;
}
void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
@@ -1650,7 +1658,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate)))
m_pp.RestTimer = 0;
SendMembership();
/* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ // looks to be in place now
//CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - sizeof(m_pp.m_player_profile_version) - 4);
// m_pp.checksum = 0; // All server out-bound player profile packets are now translated - no need to waste cycles calculating this...
outapp = new EQApplicationPacket(OP_PlayerProfile, sizeof(PlayerProfile_Struct));
@@ -1827,6 +1837,16 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
return;
}
// connected opcode handlers
void Client::Handle_0x0193(const EQApplicationPacket *app)
{
// Not sure what this opcode does. It started being sent when OP_ClientUpdate was
// changed to pump OP_ClientUpdate back out instead of OP_MobUpdate
// 2 bytes: 00 00
return;
}
void Client::Handle_OP_AAAction(const EQApplicationPacket *app)
{
LogAA("Received OP_AAAction");
@@ -4317,23 +4337,13 @@ void Client::Handle_OP_Camp(const EQApplicationPacket *app)
if (IsLFP())
worldserver.StopLFP(CharacterID());
if (ClientVersion() >= EQ::versions::ClientVersion::Laurion) {
if (!GetGM()) {
camp_timer.Start(29000, true);
}
auto outapp = new EQApplicationPacket(OP_Camp, 1);
FastQueuePacket(&outapp);
}
else {
if (GetGM())
{
OnDisconnect(true);
return;
}
camp_timer.Start(29000, true);
if (GetGM())
{
OnDisconnect(true);
return;
}
camp_timer.Start(29000, true);
return;
}
void Client::Handle_OP_CancelTask(const EQApplicationPacket *app)
@@ -6467,9 +6477,40 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
else {
auto* t = (FindPersonRequest_Struct*)app->pBuffer;
auto* m = entity_list.GetMob(t->npc_id);
switch (t->type) {
case FindLocationType::LocationPlayer: {
auto* m = entity_list.GetMob(t->id);
SendPath(m);
break;
}
case FindLocationType::LocationSwitch:
{
auto *d = entity_list.GetDoorsByDoorID(t->id);
if (d == nullptr) {
Message(Chat::Red, "Switch for find not found.");
return;
}
SendPath(m);
glm::vec3 door_loc;
door_loc.x = d->GetX();
door_loc.y = d->GetY();
door_loc.z = d->GetZ();
SendPath(door_loc);
break;
}
case FindLocationType::LocationLocation:
{
glm::vec3 target_pos;
target_pos.x = t->target_pos.x;
target_pos.y = t->target_pos.y;
target_pos.z = t->target_pos.z;
SendPath(target_pos);
break;
}
default:
break;
}
}
}
@@ -14639,10 +14680,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app)
mco->rate = 1 / buy_cost_mod;
}
if (m_ClientVersion >= EQ::versions::ClientVersion::Laurion) {
mco->player_id = GetID();
}
outapp->priority = 6;
QueuePacket(outapp);
safe_delete(outapp);
+2
View File
@@ -21,6 +21,8 @@
void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
/* Connected opcode handlers*/
void Handle_0x0193(const EQApplicationPacket *app);
void Handle_0x01e7(const EQApplicationPacket *app);
void Handle_OP_AAAction(const EQApplicationPacket *app);
void Handle_OP_AcceptNewTask(const EQApplicationPacket *app);
void Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app);
-1
View File
@@ -8,7 +8,6 @@ class Seperator;
#include <string>
#define COMMAND_CHAR '#'
#define COMMAND_CHAR_NON_HASH '$'
typedef void (*CmdFuncPtr)(Client *, const Seperator *);
+3 -18
View File
@@ -657,12 +657,7 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
} else if (zone->IsHotzone()) {
Message(Chat::Experience, "You gain party experience (with a bonus)!");
} else {
if (m_ClientVersion >= EQ::versions::ClientVersion::Laurion) {
MessageString(Chat::Experience, GAIN_GROUPXP, exp_percent_message.c_str());
}
else {
MessageString(Chat::Experience, GAIN_GROUPXP);
}
MessageString(Chat::Experience, GAIN_GROUPXP);
}
} else if (IsRaidGrouped()) {
if (RuleI(Character, ShowExpValues) > 0) {
@@ -670,12 +665,7 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
} else if (zone->IsHotzone()) {
Message(Chat::Experience, "You gained raid experience (with a bonus)!");
} else {
if (m_ClientVersion >= EQ::versions::ClientVersion::Laurion) {
MessageString(Chat::Experience, GAIN_RAIDEXP, exp_percent_message.c_str());
}
else {
MessageString(Chat::Experience, GAIN_RAIDEXP);
}
MessageString(Chat::Experience, GAIN_RAIDEXP);
}
} else {
if (RuleI(Character, ShowExpValues) > 0) {
@@ -683,12 +673,7 @@ void Client::SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool
} else if (zone->IsHotzone()) {
Message(Chat::Experience, "You gain experience (with a bonus)!");
} else {
if (m_ClientVersion >= EQ::versions::ClientVersion::Laurion) {
MessageString(Chat::Experience, GAIN_XP, exp_percent_message.c_str());
}
else {
MessageString(Chat::Experience, GAIN_XP);
}
MessageString(Chat::Experience, GAIN_XP);
}
}
}
+3
View File
@@ -674,6 +674,8 @@ luabind::scope lua_register_packet_opcodes() {
luabind::value("ShopEndConfirm", static_cast<int>(OP_ShopEndConfirm)),
luabind::value("AdventureMerchantRequest", static_cast<int>(OP_AdventureMerchantRequest)),
luabind::value("Sound", static_cast<int>(OP_Sound)),
luabind::value("0x0193", static_cast<int>(OP_0x0193)),
luabind::value("0x0347", static_cast<int>(OP_0x0347)),
luabind::value("WorldComplete", static_cast<int>(OP_WorldComplete)),
luabind::value("MobRename", static_cast<int>(OP_MobRename)),
luabind::value("TaskDescription", static_cast<int>(OP_TaskDescription)),
@@ -837,6 +839,7 @@ luabind::scope lua_register_packet_opcodes() {
luabind::value("GroupLeaderChange", static_cast<int>(OP_GroupLeaderChange)),
luabind::value("GroupLeadershipAAUpdate", static_cast<int>(OP_GroupLeadershipAAUpdate)),
luabind::value("GroupRoles", static_cast<int>(OP_GroupRoles)),
luabind::value("OP_SendFindableLocations", static_cast<int>(OP_SendFindableLocations)),
luabind::value("SendFindableNPCs", static_cast<int>(OP_SendFindableNPCs)),
luabind::value("HideCorpse", static_cast<int>(OP_HideCorpse)),
luabind::value("TargetBuffs", static_cast<int>(OP_TargetBuffs)),
-8
View File
@@ -1275,14 +1275,6 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
strcpy(ns->spawn.name, name);
if(IsClient()) {
strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName));
ns->spawn.CharacterGuid.Id = CastToClient()->CharacterID();
ns->spawn.CharacterGuid.WorldId = RuleI(World, Id);
ns->spawn.CharacterGuid.Reserved = 0;
}
else {
ns->spawn.CharacterGuid.Id = 0;
ns->spawn.CharacterGuid.WorldId = 0;
ns->spawn.CharacterGuid.Reserved = 0;
}
ns->spawn.heading = FloatToEQ12(m_Position.w);
+10 -13
View File
@@ -72,22 +72,19 @@ void Client::SendPathPacket(const std::vector<FindPerson_Point> &points) {
Message(Chat::System, "Total points %u", points.size());
}
int len = sizeof(FindPersonResult_Struct) + (points.size() + 1) * sizeof(FindPerson_Point);
int len = (points.size() + 1) * sizeof(FindPerson_Point);
auto outapp = new EQApplicationPacket(OP_FindPersonReply, len);
FindPersonResult_Struct* fpr = (FindPersonResult_Struct*)outapp->pBuffer;
std::vector<FindPerson_Point>::iterator cur, end;
cur = points.begin();
end = points.end();
unsigned int r;
for (r = 0; cur != end; ++cur, r++) {
fpr->path[r] = *cur;
auto& last = points.back();
outapp->WriteFloat(last.y);
outapp->WriteFloat(last.x);
outapp->WriteFloat(last.z);
for (auto& p : points) {
outapp->WriteFloat(p.y);
outapp->WriteFloat(p.x);
outapp->WriteFloat(p.z);
}
//put the last element into the destination field
--cur;
fpr->path[r] = *cur;
fpr->dest = *cur;
FastQueuePacket(&outapp);
})
+9
View File
@@ -2005,6 +2005,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
break;
}
case ServerOP_ReloadFindableLocations:
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Findable Locations");
zone->ReloadFindableLocations();
}
break;
}
case ServerOP_ReloadBlockedSpells:
{
if (zone && zone->IsLoaded()) {
+1
View File
@@ -1200,6 +1200,7 @@ bool Zone::Init(bool is_static) {
LoadNPCEmotes(&npc_emote_list);
LoadAlternateAdvancement();
LoadBaseData();
LoadFindableLocations();
LoadMerchants();
LoadTempMerchantData();
+10
View File
@@ -47,6 +47,7 @@
#include "../common/repositories/lootdrop_entries_repository.h"
#include "../common/repositories/base_data_repository.h"
#include "../common/repositories/skill_caps_repository.h"
#include "../common/repositories/findable_location_repository.h"
struct EXPModifier
{
@@ -454,6 +455,12 @@ public:
void LoadBaseData();
void ReloadBaseData();
// Findable Locations
void LoadFindableLocations();
void ReloadFindableLocations();
void ClearFindableLocations();
void SendFindableLocations(Client* client = nullptr);
private:
bool allow_mercs;
@@ -518,6 +525,9 @@ private:
// Base Data
std::vector<BaseDataRepository::BaseData> m_base_data = { };
// Findable Locations
std::vector<FindableLocationRepository::FindableLocation> m_findable_locations = { };
};
#endif
+42
View File
@@ -0,0 +1,42 @@
#include "zone.h"
void Zone::LoadFindableLocations() {
m_findable_locations = content_db.LoadFindableLocations(GetShortName(), GetInstanceVersion());
if (m_findable_locations.empty()) {
LogInfo("No findable loacations loaded");
return;
}
}
void Zone::ReloadFindableLocations() {
ClearFindableLocations();
LoadFindableLocations();
}
void Zone::ClearFindableLocations() {
m_findable_locations.clear();
}
void Zone::SendFindableLocations(Client* client) {
if (m_findable_locations.empty()) {
return;
}
size_t size = sizeof(uint32) + (m_findable_locations.size() * sizeof(FindableLocation_Struct));
auto outapp = new EQApplicationPacket(OP_SendFindableLocations, size);
outapp->WriteUInt32(m_findable_locations.size());
for (auto& location : m_findable_locations) {
outapp->WriteUInt32(location.type);
outapp->WriteSInt32(location.findable_id);
outapp->WriteSInt32(location.findable_sub_id);
outapp->WriteSInt32(location.zone_id);
outapp->WriteSInt32(location.zone_id_index);
outapp->WriteFloat(location.y);
outapp->WriteFloat(location.x);
outapp->WriteFloat(location.z);
}
client->FastQueuePacket(&outapp);
}
+10 -2
View File
@@ -50,9 +50,8 @@
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/character_corpse_items_repository.h"
#include "../common/repositories/zone_repository.h"
#include "../common/repositories/trader_repository.h"
#include "../common/repositories/findable_location_repository.h"
#include <ctime>
#include <iostream>
@@ -2875,6 +2874,15 @@ void ZoneDatabase::UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, ui
CharacterAltCurrencyRepository::ReplaceOne(*this, e);
}
std::vector<FindableLocationRepository::FindableLocation> ZoneDatabase::LoadFindableLocations(const std::string& zone_name, int16 version) {
auto findable_locations = FindableLocationRepository::GetWhere(
*this, fmt::format(
"zone = '{}' AND (version = {} OR version = -1) {} ORDER BY id ASC",
zone_name, version, ContentFilterCriteria::apply()));
return findable_locations;
}
void ZoneDatabase::SaveBuffs(Client *client)
{
CharacterBuffsRepository::DeleteWhere(
+4
View File
@@ -13,6 +13,7 @@
#include "../common/repositories/doors_repository.h"
#include "../common/races.h"
#include "../common/repositories/npc_faction_entries_repository.h"
#include "../common/repositories/findable_location_repository.h"
#include "bot_database.h"
@@ -638,6 +639,9 @@ public:
void LoadAltCurrencyValues(uint32 char_id, std::map<uint32, uint32> &currency);
void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value);
/* Findable Locations */
std::vector<FindableLocationRepository::FindableLocation> LoadFindableLocations(const std::string& zone_name, int16 version);
/*
* Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD