mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 18:51:29 +00:00
More work to actually make this usable
This commit is contained in:
parent
923252dbcc
commit
a6675a483d
@ -29,6 +29,7 @@ SET(common_sources
|
|||||||
extprofile.cpp
|
extprofile.cpp
|
||||||
faction.cpp
|
faction.cpp
|
||||||
file_verify.cpp
|
file_verify.cpp
|
||||||
|
file_verify_manager.cpp
|
||||||
guild_base.cpp
|
guild_base.cpp
|
||||||
guilds.cpp
|
guilds.cpp
|
||||||
ipc_mutex.cpp
|
ipc_mutex.cpp
|
||||||
@ -132,6 +133,7 @@ SET(common_headers
|
|||||||
faction.h
|
faction.h
|
||||||
features.h
|
features.h
|
||||||
file_verify.h
|
file_verify.h
|
||||||
|
file_verify_manager.h
|
||||||
fixed_memory_hash_set.h
|
fixed_memory_hash_set.h
|
||||||
fixed_memory_variable_hash_set.h
|
fixed_memory_variable_hash_set.h
|
||||||
global_define.h
|
global_define.h
|
||||||
|
|||||||
@ -55,6 +55,8 @@ enum class ClientVersion
|
|||||||
MobMerc,
|
MobMerc,
|
||||||
MobBot,
|
MobBot,
|
||||||
MobPet,
|
MobPet,
|
||||||
|
|
||||||
|
MaxClientVersions
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLIENT_VERSION_COUNT 12
|
#define CLIENT_VERSION_COUNT 12
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
#include "global_define.h"
|
#include "global_define.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "clientversions.h"
|
||||||
#include "file_verify.h"
|
#include "file_verify.h"
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
struct VerifyFileStruct
|
struct VerifyFileStruct
|
||||||
{
|
{
|
||||||
uint32 crc;
|
uint32 crc;
|
||||||
@ -11,21 +13,33 @@ struct VerifyFileStruct
|
|||||||
uint32 offset[256];
|
uint32 offset[256];
|
||||||
uint32 data[256];
|
uint32 data[256];
|
||||||
};
|
};
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
EQEmu::FileVerify::FileVerify() {
|
||||||
|
buffer = nullptr;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQEmu::FileVerify::~FileVerify() {
|
||||||
|
safe_delete_array(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQEmu::FileVerify::Load(const char *file_name) {
|
||||||
|
safe_delete_array(buffer);
|
||||||
|
size = 0;
|
||||||
|
|
||||||
EQEmu::FileVerify::FileVerify(const char *file_name) {
|
|
||||||
FILE *f = fopen(file_name, "rb");
|
FILE *f = fopen(file_name, "rb");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
buffer = nullptr;
|
buffer = nullptr;
|
||||||
size = 0;
|
size = 0;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(f, 0U, SEEK_END);
|
fseek(f, 0U, SEEK_END);
|
||||||
size = ftell(f);
|
size = ftell(f);
|
||||||
rewind(f);
|
rewind(f);
|
||||||
|
|
||||||
char *buffer = new char[size];
|
buffer = new char[size];
|
||||||
auto result = fread(buffer, 1, size, f);
|
auto result = fread(buffer, 1, size, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
@ -33,13 +47,11 @@ EQEmu::FileVerify::FileVerify(const char *file_name) {
|
|||||||
safe_delete_array(buffer);
|
safe_delete_array(buffer);
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQEmu::FileVerify::~FileVerify() {
|
bool EQEmu::FileVerify::Verify(const char *data, uint32 size, ClientVersion version) {
|
||||||
safe_delete_array(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EQEmu::FileVerify::Verify(const char *data, uint32 size) {
|
|
||||||
if(!buffer) {
|
if(!buffer) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -49,11 +61,11 @@ bool EQEmu::FileVerify::Verify(const char *data, uint32 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VerifyFileStruct *vs = (VerifyFileStruct*)data;
|
VerifyFileStruct *vs = (VerifyFileStruct*)data;
|
||||||
if(size != vs->file_size) {
|
if(this->size != vs->file_size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 crc = CRC32::GenerateNoFlip((uchar*)buffer, size);
|
uint32 crc = CRC32::GenerateNoFlip((uchar*)buffer, this->size);
|
||||||
if(vs->crc != crc) {
|
if(vs->crc != crc) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -61,7 +73,7 @@ bool EQEmu::FileVerify::Verify(const char *data, uint32 size) {
|
|||||||
for(int i = 0; i < 256; ++i) {
|
for(int i = 0; i < 256; ++i) {
|
||||||
uint32 offset = vs->offset[i] * 4;
|
uint32 offset = vs->offset[i] * 4;
|
||||||
|
|
||||||
if((offset - 4) > size) {
|
if((offset - 4) > this->size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,50 +86,3 @@ bool EQEmu::FileVerify::Verify(const char *data, uint32 size) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool VerifyFile(const EQApplicationPacket *app, const char* filename) {
|
|
||||||
// FILE *f = fopen(filename, "rb");
|
|
||||||
// if(!f) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// VerifyFileStruct *vs = (VerifyFileStruct*)app->pBuffer;
|
|
||||||
//
|
|
||||||
// fseek(f, 0U, SEEK_END);
|
|
||||||
// auto size = ftell(f);
|
|
||||||
// rewind(f);
|
|
||||||
//
|
|
||||||
// if(size != vs->file_size || size < 1024) {
|
|
||||||
// fclose(f);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// char *buffer = new char[size];
|
|
||||||
// std::unique_ptr<char> data(buffer);
|
|
||||||
// auto result = fread(buffer, 1, size, f);
|
|
||||||
// fclose(f);
|
|
||||||
//
|
|
||||||
// if(result != size) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// uint32 crc = CRC32::GenerateNoFlip((uchar*)buffer, size);
|
|
||||||
//
|
|
||||||
// Log.Out(Logs::General, Logs::Status, "CRC %u vs %u", crc, vs->crc);
|
|
||||||
//
|
|
||||||
// for(int i = 0; i < 256; ++i) {
|
|
||||||
// uint32 offset = vs->check[i] * 4;
|
|
||||||
//
|
|
||||||
// Log.Out(Logs::General, Logs::Status, "Data: %c%c%c%c vs %c%c%c%c", vs->data[i * 4], vs->data[i * 4 + 1], vs->data[i * 4 + 2], vs->data[i * 4 + 3],
|
|
||||||
// buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3]);
|
|
||||||
//
|
|
||||||
// if(buffer[offset] != vs->data[i * 4] ||
|
|
||||||
// buffer[offset + 1] != vs->data[i * 4 + 1] ||
|
|
||||||
// buffer[offset + 2] != vs->data[i * 4 + 2] ||
|
|
||||||
// buffer[offset + 3] != vs->data[i * 4 + 3])
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
@ -6,10 +6,11 @@ namespace EQEmu
|
|||||||
class FileVerify
|
class FileVerify
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileVerify(const char *file_name);
|
FileVerify();
|
||||||
~FileVerify();
|
~FileVerify();
|
||||||
|
|
||||||
bool Verify(const char *data, uint32 size);
|
bool Load(const char *file_name);
|
||||||
|
bool Verify(const char *data, uint32 size, ClientVersion version);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|||||||
87
common/file_verify_manager.cpp
Normal file
87
common/file_verify_manager.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "global_define.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "clientversions.h"
|
||||||
|
#include "eq_packet.h"
|
||||||
|
#include "file_verify_manager.h"
|
||||||
|
#include "string_util.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct EQEmu::FileVerifyManager::impl {
|
||||||
|
std::unique_ptr<FileVerify> spell_data;
|
||||||
|
std::unique_ptr<FileVerify> skill_data;
|
||||||
|
std::unique_ptr<FileVerify> base_data;
|
||||||
|
std::unique_ptr<FileVerify> eqgames[(int)ClientVersion::MaxClientVersions];
|
||||||
|
};
|
||||||
|
|
||||||
|
EQEmu::FileVerifyManager::FileVerifyManager() {
|
||||||
|
impl_ = new impl;
|
||||||
|
impl_->spell_data.reset(new FileVerify());
|
||||||
|
impl_->spell_data->Load("verify/spells_us.txt");
|
||||||
|
|
||||||
|
impl_->skill_data.reset(new FileVerify());
|
||||||
|
impl_->skill_data->Load("verify/SkillCaps.txt");
|
||||||
|
|
||||||
|
impl_->base_data.reset(new FileVerify());
|
||||||
|
impl_->base_data->Load("verify/BaseData.txt");
|
||||||
|
|
||||||
|
for(int i = 0; i < (int)ClientVersion::MaxClientVersions; ++i) {
|
||||||
|
impl_->eqgames[i].reset(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQEmu::FileVerifyManager::~FileVerifyManager() {
|
||||||
|
delete impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQEmu::FileVerifyManager::VerifySpellFile(const EQApplicationPacket *app, ClientVersion version) {
|
||||||
|
if(!impl_->spell_data) {
|
||||||
|
impl_->spell_data.reset(new FileVerify());
|
||||||
|
|
||||||
|
if(!impl_->spell_data->Load("verify/spells_us.txt")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return impl_->spell_data->Verify((char*)app->pBuffer, app->size, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQEmu::FileVerifyManager::VerifySkillFile(const EQApplicationPacket *app, ClientVersion version) {
|
||||||
|
if(!impl_->skill_data) {
|
||||||
|
impl_->skill_data.reset(new FileVerify());
|
||||||
|
|
||||||
|
if(!impl_->skill_data->Load("verify/SkillCaps.txt")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return impl_->skill_data->Verify((char*)app->pBuffer, app->size, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQEmu::FileVerifyManager::VerifyBaseDataFile(const EQApplicationPacket *app, ClientVersion version) {
|
||||||
|
if(!impl_->base_data) {
|
||||||
|
impl_->base_data.reset(new FileVerify());
|
||||||
|
|
||||||
|
if(!impl_->base_data->Load("verify/BaseData.txt")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return impl_->base_data->Verify((char*)app->pBuffer, app->size, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EQEmu::FileVerifyManager::VerifyEQGame(const EQApplicationPacket *app, ClientVersion version) {
|
||||||
|
int v = (int)version;
|
||||||
|
if(v >= (int)ClientVersion::MaxClientVersions) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!impl_->eqgames[v]) {
|
||||||
|
impl_->eqgames[v].reset(new FileVerify());
|
||||||
|
|
||||||
|
if(!impl_->eqgames[v]->Load(StringFormat("verify/%s/eqgame.exe", ClientVersionName(version)).c_str())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return impl_->eqgames[v]->Verify((char*)app->pBuffer, app->size, version);
|
||||||
|
}
|
||||||
33
common/file_verify_manager.h
Normal file
33
common/file_verify_manager.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef EQEMU_COMMON_FILE_VERIFY_MANAGER_H
|
||||||
|
#define EQEMU_COMMON_FILE_VERIFY_MANAGER_H
|
||||||
|
|
||||||
|
#include "file_verify.h"
|
||||||
|
|
||||||
|
namespace EQEmu
|
||||||
|
{
|
||||||
|
class FileVerifyManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~FileVerifyManager();
|
||||||
|
|
||||||
|
static FileVerifyManager& Get()
|
||||||
|
{
|
||||||
|
static FileVerifyManager instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerifySpellFile(const EQApplicationPacket *app, ClientVersion version);
|
||||||
|
bool VerifySkillFile(const EQApplicationPacket *app, ClientVersion version);
|
||||||
|
bool VerifyBaseDataFile(const EQApplicationPacket *app, ClientVersion version);
|
||||||
|
bool VerifyEQGame(const EQApplicationPacket *app, ClientVersion version);
|
||||||
|
private:
|
||||||
|
FileVerifyManager();
|
||||||
|
FileVerifyManager(FileVerifyManager const&);
|
||||||
|
void operator=(FileVerifyManager const&);
|
||||||
|
|
||||||
|
struct impl;
|
||||||
|
impl *impl_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -188,6 +188,7 @@ RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
|
|||||||
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
|
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
|
||||||
RULE_BOOL (World, IPLimitDisconnectAll, false)
|
RULE_BOOL (World, IPLimitDisconnectAll, false)
|
||||||
RULE_INT (World, TellQueueSize, 20)
|
RULE_INT (World, TellQueueSize, 20)
|
||||||
|
RULE_BOOL (World, AllowActionWithBadFiles, true) // if false then the client will be prevented from moving past world if their client files don't match the server's
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
|
|||||||
@ -153,6 +153,8 @@
|
|||||||
#define ServerOP_GetWorldTime 0x200C
|
#define ServerOP_GetWorldTime 0x200C
|
||||||
#define ServerOP_SyncWorldTime 0x200E
|
#define ServerOP_SyncWorldTime 0x200E
|
||||||
|
|
||||||
|
#define ServerOP_ClientFileStatus 0x2020
|
||||||
|
|
||||||
#define ServerOP_LSZoneInfo 0x3001
|
#define ServerOP_LSZoneInfo 0x3001
|
||||||
#define ServerOP_LSZoneStart 0x3002
|
#define ServerOP_LSZoneStart 0x3002
|
||||||
#define ServerOP_LSZoneBoot 0x3003
|
#define ServerOP_LSZoneBoot 0x3003
|
||||||
@ -1263,6 +1265,22 @@ struct ServerRequestTellQueue_Struct {
|
|||||||
char name[64];
|
char name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ServerRequestClientFileStatus
|
||||||
|
{
|
||||||
|
int zone_id;
|
||||||
|
int instance_id;
|
||||||
|
char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerResponseClientFileStatus
|
||||||
|
{
|
||||||
|
char name[64];
|
||||||
|
bool spells;
|
||||||
|
bool skills;
|
||||||
|
bool base_data;
|
||||||
|
bool eqgame;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -22,10 +22,10 @@ OP_ExpansionInfo=0x711a
|
|||||||
OP_GuildsList=0x2d38
|
OP_GuildsList=0x2d38
|
||||||
OP_EnterWorld=0x57c3
|
OP_EnterWorld=0x57c3
|
||||||
OP_PostEnterWorld=0x0c3d
|
OP_PostEnterWorld=0x0c3d
|
||||||
OP_World_Client_CRC1=0x0044
|
OP_World_SpellFileCheck=0x0000 # appears to be removed in RoF, maybe 0x0044? I don't have a client to check
|
||||||
OP_World_Client_CRC2=0x26df
|
OP_World_SkillFileCheck=0x0000
|
||||||
OP_SendSpellChecksum=0x0000
|
OP_World_BaseDataFileCheck=0x0000
|
||||||
OP_SendSkillCapsChecksum=0x0000
|
OP_World_ExeFileCheck=0x26df
|
||||||
|
|
||||||
# Character Select Related:
|
# Character Select Related:
|
||||||
OP_SendMaxCharacters=0x5349
|
OP_SendMaxCharacters=0x5349
|
||||||
|
|||||||
@ -22,10 +22,10 @@ OP_ExpansionInfo=0x590d
|
|||||||
OP_GuildsList=0x507a
|
OP_GuildsList=0x507a
|
||||||
OP_EnterWorld=0x578f
|
OP_EnterWorld=0x578f
|
||||||
OP_PostEnterWorld=0x6259
|
OP_PostEnterWorld=0x6259
|
||||||
OP_World_Client_CRC1=0x12cc
|
OP_World_SpellFileCheck=0x0000 # appears to be removed in RoF
|
||||||
OP_World_Client_CRC2=0x0f13
|
OP_World_SkillFileCheck=0x4b8d
|
||||||
OP_SendSpellChecksum=0x0000
|
OP_World_BaseDataFileCheck=0x298d
|
||||||
OP_SendSkillCapsChecksum=0x0000
|
OP_World_ExeFileCheck=0x0f13
|
||||||
|
|
||||||
# Character Select Related:
|
# Character Select Related:
|
||||||
OP_SendMaxCharacters=0x5475
|
OP_SendMaxCharacters=0x5475
|
||||||
|
|||||||
@ -26,10 +26,10 @@ OP_ExpansionInfo=0x7519 # C
|
|||||||
OP_GuildsList=0x5b0b # C
|
OP_GuildsList=0x5b0b # C
|
||||||
OP_EnterWorld=0x1c20 # C
|
OP_EnterWorld=0x1c20 # C
|
||||||
OP_PostEnterWorld=0x7c94 # C
|
OP_PostEnterWorld=0x7c94 # C
|
||||||
OP_World_Client_CRC1=0x0ca5 # C
|
OP_World_SpellFileCheck=0x0ca5 # C
|
||||||
OP_World_Client_CRC2=0x1cb3 # C
|
OP_World_SkillFileCheck=0x5bad # C
|
||||||
OP_SendSpellChecksum=0x5bad # C
|
OP_World_BaseDataFileCheck=0x5d24 # C
|
||||||
OP_SendSkillCapsChecksum=0x5d24 # C
|
OP_World_ExeFileCheck=0x1cb3 # C
|
||||||
|
|
||||||
# Character Select Related:
|
# Character Select Related:
|
||||||
OP_DeleteCharacter=0x0254 # C
|
OP_DeleteCharacter=0x0254 # C
|
||||||
|
|||||||
@ -23,10 +23,10 @@ OP_ExpansionInfo=0x0A1B #SEQ 12/04/08
|
|||||||
OP_GuildsList=0x04FB #SEQ 12/04/08
|
OP_GuildsList=0x04FB #SEQ 12/04/08
|
||||||
OP_EnterWorld=0x1340 #SEQ 12/04/08
|
OP_EnterWorld=0x1340 #SEQ 12/04/08
|
||||||
OP_PostEnterWorld=0x1AEE #SEQ 12/04/08
|
OP_PostEnterWorld=0x1AEE #SEQ 12/04/08
|
||||||
OP_World_Client_CRC1=0x7A9E #SEQ 12/04/08
|
OP_World_SpellFileCheck=0x7A9E #these are guessed but should be right I hope, who even uses SoF though
|
||||||
OP_World_Client_CRC2=0x3795 #SEQ 12/04/08
|
OP_World_ExeFileCheck=0x3795
|
||||||
OP_SendSpellChecksum=0x22CF #SEQ 12/04/08
|
OP_World_BaseDataFileCheck=0x22CF
|
||||||
OP_SendSkillCapsChecksum=0x43BA #SEQ 12/04/08
|
OP_SendSkillCapsChecksum=0x43BA
|
||||||
|
|
||||||
#Character Select Related:
|
#Character Select Related:
|
||||||
OP_DeleteCharacter=0x789F #SEQ 12/04/08
|
OP_DeleteCharacter=0x789F #SEQ 12/04/08
|
||||||
|
|||||||
@ -27,8 +27,6 @@ OP_GuildsList=0x6957 #same as zone guild list afaik
|
|||||||
OP_ApproveName=0x3ea6 # EQEmu 11/28/05
|
OP_ApproveName=0x3ea6 # EQEmu 11/28/05
|
||||||
OP_EnterWorld=0x7cba # ShowEQ 10/27/05
|
OP_EnterWorld=0x7cba # ShowEQ 10/27/05
|
||||||
OP_PostEnterWorld=0x52A4 # EQEmu 06/29/05
|
OP_PostEnterWorld=0x52A4 # EQEmu 06/29/05
|
||||||
OP_World_Client_CRC1=0x5072 # ShowEQ 10/27/05
|
|
||||||
OP_World_Client_CRC2=0x5b18 # ShowEQ 10/27/05
|
|
||||||
OP_SetChatServer=0x00d7 # ShowEQ 10/27/05
|
OP_SetChatServer=0x00d7 # ShowEQ 10/27/05
|
||||||
OP_SetChatServer2=0x6536 # ShowEQ 10/27/05
|
OP_SetChatServer2=0x6536 # ShowEQ 10/27/05
|
||||||
OP_ZoneServerInfo=0x61b6 # ShowEQ 10/27/05
|
OP_ZoneServerInfo=0x61b6 # ShowEQ 10/27/05
|
||||||
@ -42,6 +40,10 @@ OP_WorldLoginFailed=0x8DA7 # world->client. reject.
|
|||||||
OP_WorldLogout=0x7718 # client->world
|
OP_WorldLogout=0x7718 # client->world
|
||||||
OP_WorldLevelTooHigh=0x583b # world->client. Cancels zone in.
|
OP_WorldLevelTooHigh=0x583b # world->client. Cancels zone in.
|
||||||
OP_CharInacessable=0x436A # world->client. Cancels zone in.
|
OP_CharInacessable=0x436A # world->client. Cancels zone in.
|
||||||
|
OP_World_SpellFileCheck=0x5072
|
||||||
|
OP_World_SkillFileCheck=0x0000
|
||||||
|
OP_World_BaseDataFileCheck=0x0000
|
||||||
|
OP_World_ExeFileCheck=0x5b18
|
||||||
|
|
||||||
#Zone in opcodes
|
#Zone in opcodes
|
||||||
OP_ZoneEntry=0x7213 # ShowEQ 10/27/05
|
OP_ZoneEntry=0x7213 # ShowEQ 10/27/05
|
||||||
|
|||||||
@ -26,10 +26,10 @@ OP_ExpansionInfo=0x7e4d # C
|
|||||||
OP_GuildsList=0x5b0b # C
|
OP_GuildsList=0x5b0b # C
|
||||||
OP_EnterWorld=0x51b9 # C
|
OP_EnterWorld=0x51b9 # C
|
||||||
OP_PostEnterWorld=0x5d32 # C
|
OP_PostEnterWorld=0x5d32 # C
|
||||||
OP_World_Client_CRC1=0x3a18 # C
|
OP_World_SpellFileCheck=0x3a18
|
||||||
OP_World_Client_CRC2=0x3e50 # C
|
OP_World_SkillFileCheck=0x46d3
|
||||||
OP_SendSpellChecksum=0x46d3 # C
|
OP_World_BaseDataFileCheck=0x040b
|
||||||
OP_SendSkillCapsChecksum=0x040b # C
|
OP_World_ExeFileCheck=0x3e50
|
||||||
|
|
||||||
# Character Select Related:
|
# Character Select Related:
|
||||||
OP_DeleteCharacter=0x5ca5 # C
|
OP_DeleteCharacter=0x5ca5 # C
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
#include "../common/clientversions.h"
|
#include "../common/clientversions.h"
|
||||||
#include "../common/random.h"
|
#include "../common/random.h"
|
||||||
#include "../common/shareddb.h"
|
#include "../common/shareddb.h"
|
||||||
#include "../common/file_verify.h"
|
#include "../common/file_verify_manager.h"
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "worlddb.h"
|
#include "worlddb.h"
|
||||||
@ -61,11 +61,6 @@
|
|||||||
std::vector<RaceClassAllocation> character_create_allocations;
|
std::vector<RaceClassAllocation> character_create_allocations;
|
||||||
std::vector<RaceClassCombos> character_create_race_class_combos;
|
std::vector<RaceClassCombos> character_create_race_class_combos;
|
||||||
|
|
||||||
EQEmu::FileVerify spell_verify("verify/spells_us.txt");
|
|
||||||
EQEmu::FileVerify skills_verify("verify/SkillCaps.txt");
|
|
||||||
EQEmu::FileVerify basedata_verify("verify/BaseData.txt");
|
|
||||||
EQEmu::FileVerify eqgame_verify("verify/eqgame.exe");
|
|
||||||
|
|
||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
extern LoginServerList loginserverlist;
|
extern LoginServerList loginserverlist;
|
||||||
extern ClientList client_list;
|
extern ClientList client_list;
|
||||||
@ -96,7 +91,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
|
|
||||||
m_ClientVersion = eqs->GetClientVersion();
|
m_ClientVersion = eqs->GetClientVersion();
|
||||||
m_ClientVersionBit = ClientBitFromVersion(m_ClientVersion);
|
m_ClientVersionBit = ClientBitFromVersion(m_ClientVersion);
|
||||||
|
|
||||||
numclients++;
|
numclients++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,6 +606,10 @@ bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app) {
|
bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app) {
|
||||||
|
if(!CanTakeAction()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// New OpCode in SoF
|
// New OpCode in SoF
|
||||||
uint32 allocs = character_create_allocations.size();
|
uint32 allocs = character_create_allocations.size();
|
||||||
uint32 combos = character_create_race_class_combos.size();
|
uint32 combos = character_create_race_class_combos.size();
|
||||||
@ -658,6 +657,10 @@ bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||||
|
if(!CanTakeAction()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetAccountID() == 0) {
|
if (GetAccountID() == 0) {
|
||||||
Log.Out(Logs::Detail, Logs::World_Server,"Account ID not set; unable to create character.");
|
Log.Out(Logs::Detail, Logs::World_Server,"Account ID not set; unable to create character.");
|
||||||
return false;
|
return false;
|
||||||
@ -689,6 +692,11 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||||
|
if(!CanTakeAction()) {
|
||||||
|
ZoneUnavail();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetAccountID() == 0) {
|
if (GetAccountID() == 0) {
|
||||||
Log.Out(Logs::Detail, Logs::World_Server,"Enter world with no logged in account");
|
Log.Out(Logs::Detail, Logs::World_Server,"Enter world with no logged in account");
|
||||||
eqs->Close();
|
eqs->Close();
|
||||||
@ -908,6 +916,9 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
|
bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) {
|
||||||
|
if(!CanTakeAction()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer);
|
||||||
if(char_acct_id == GetAccountID()) {
|
if(char_acct_id == GetAccountID()) {
|
||||||
@ -960,49 +971,66 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
{
|
{
|
||||||
case OP_World_SpellFileCheck:
|
case OP_World_SpellFileCheck:
|
||||||
{
|
{
|
||||||
if(spell_verify.Verify((char*)app->pBuffer, app->Size())) {
|
if(EQEmu::FileVerifyManager::Get().VerifySpellFile(app, eqs->GetClientVersion())) {
|
||||||
Log.Out(Logs::General, Logs::Status, "Spell file verified.");
|
if(cle) {
|
||||||
|
cle->SetSpellFileVerified(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.Out(Logs::General, Logs::Status, "Spell file not verified.");
|
if(cle) {
|
||||||
|
cle->SetSpellFileVerified(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
StartInTutorial = false;
|
StartInTutorial = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_World_SkillFileCheck:
|
case OP_World_SkillFileCheck:
|
||||||
{
|
{
|
||||||
if(skills_verify.Verify((char*)app->pBuffer, app->Size())) {
|
if(EQEmu::FileVerifyManager::Get().VerifySkillFile(app, eqs->GetClientVersion())) {
|
||||||
Log.Out(Logs::General, Logs::Status, "Skill file verified.");
|
if(cle) {
|
||||||
|
cle->SetSkillFileVerified(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.Out(Logs::General, Logs::Status, "Skill file not verified.");
|
if(cle) {
|
||||||
|
cle->SetSkillFileVerified(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
StartInTutorial = false;
|
StartInTutorial = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_World_BaseDataFileCheck:
|
case OP_World_BaseDataFileCheck:
|
||||||
{
|
{
|
||||||
if(basedata_verify.Verify((char*)app->pBuffer, app->Size())) {
|
if(EQEmu::FileVerifyManager::Get().VerifyBaseDataFile(app, eqs->GetClientVersion())) {
|
||||||
Log.Out(Logs::General, Logs::Status, "BaseData file verified.");
|
if(cle) {
|
||||||
|
cle->SetBaseDataFileVerified(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.Out(Logs::General, Logs::Status, "BaseData file not verified.");
|
if(cle) {
|
||||||
|
cle->SetBaseDataFileVerified(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartInTutorial = false;
|
StartInTutorial = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_World_ExeFileCheck:
|
case OP_World_ExeFileCheck:
|
||||||
{
|
{
|
||||||
if(eqgame_verify.Verify((char*)app->pBuffer, app->Size())) {
|
if(EQEmu::FileVerifyManager::Get().VerifyEQGame(app, eqs->GetClientVersion())) {
|
||||||
Log.Out(Logs::General, Logs::Status, "eqgame.exe verified.");
|
if(cle) {
|
||||||
|
cle->SetEQGameVerified(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.Out(Logs::General, Logs::Status, "eqgame.exe not verified.");
|
if(cle) {
|
||||||
|
cle->SetEQGameVerified(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartInTutorial = false;
|
StartInTutorial = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_SendLoginInfo:
|
case OP_SendLoginInfo:
|
||||||
{
|
{
|
||||||
return HandleSendLoginInfoPacket(app);
|
return HandleSendLoginInfoPacket(app);
|
||||||
@ -1048,21 +1076,15 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
|||||||
case OP_ApproveWorld:
|
case OP_ApproveWorld:
|
||||||
case OP_WorldClientReady:
|
case OP_WorldClientReady:
|
||||||
{
|
{
|
||||||
//char buffer[64];
|
|
||||||
//app->build_header_dump(buffer);
|
|
||||||
//Log.Out(Logs::General, Logs::Status, "%s %s", buffer, DumpPacketToString(app).c_str());
|
|
||||||
|
|
||||||
// Essentially we are just 'eating' these packets, indicating
|
|
||||||
// they are handled.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Log.Out(Logs::Detail, Logs::World_Server,"Received unknown EQApplicationPacket");
|
Log.Out(Logs::Detail, Logs::World_Server,"Received unknown EQApplicationPacket");
|
||||||
|
|
||||||
//char buffer[64];
|
char buffer[64];
|
||||||
//app->build_header_dump(buffer);
|
app->build_header_dump(buffer);
|
||||||
//Log.Out(Logs::General, Logs::Status, "%s %s", buffer, DumpPacketToString(app).c_str());
|
Log.Out(Logs::General, Logs::Status, "%s %s", buffer, DumpPacketToString(app).c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2035,3 +2057,14 @@ void Client::SetClassLanguages(PlayerProfile_Struct *pp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Client::CanTakeAction() {
|
||||||
|
if(RuleB(World, AllowActionWithBadFiles)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!cle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cle->GetBaseDataFileVerified() && cle->GetEQGameVerified() && cle->GetSkillFileVerified() && cle->GetSpellFileVerified();
|
||||||
|
}
|
||||||
|
|||||||
@ -100,6 +100,8 @@ private:
|
|||||||
bool seencharsel;
|
bool seencharsel;
|
||||||
bool realfirstlogin;
|
bool realfirstlogin;
|
||||||
|
|
||||||
|
bool CanTakeAction();
|
||||||
|
|
||||||
bool HandlePacket(const EQApplicationPacket *app);
|
bool HandlePacket(const EQApplicationPacket *app);
|
||||||
bool HandleNameApprovalPacket(const EQApplicationPacket *app);
|
bool HandleNameApprovalPacket(const EQApplicationPacket *app);
|
||||||
bool HandleSendLoginInfoPacket(const EQApplicationPacket *app);
|
bool HandleSendLoginInfoPacket(const EQApplicationPacket *app);
|
||||||
|
|||||||
@ -46,6 +46,11 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char* iLoginN
|
|||||||
plocal=(local==1);
|
plocal=(local==1);
|
||||||
|
|
||||||
pinstance = 0;
|
pinstance = 0;
|
||||||
|
|
||||||
|
spell_file_verified = true;
|
||||||
|
skill_file_verified = true;
|
||||||
|
base_data_file_verified = true;
|
||||||
|
eqgame_file_verified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
|
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
|
||||||
@ -63,6 +68,11 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccNa
|
|||||||
padmin = iAdmin;
|
padmin = iAdmin;
|
||||||
|
|
||||||
pinstance = 0;
|
pinstance = 0;
|
||||||
|
|
||||||
|
spell_file_verified = true;
|
||||||
|
skill_file_verified = true;
|
||||||
|
base_data_file_verified = true;
|
||||||
|
eqgame_file_verified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
|
||||||
@ -86,6 +96,11 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
|
|||||||
Update(iZS, scl, iOnline);
|
Update(iZS, scl, iOnline);
|
||||||
else
|
else
|
||||||
SetOnline(iOnline);
|
SetOnline(iOnline);
|
||||||
|
|
||||||
|
spell_file_verified = true;
|
||||||
|
skill_file_verified = true;
|
||||||
|
base_data_file_verified = true;
|
||||||
|
eqgame_file_verified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientListEntry::~ClientListEntry() {
|
ClientListEntry::~ClientListEntry() {
|
||||||
|
|||||||
@ -87,6 +87,16 @@ public:
|
|||||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||||
void ProcessTellQueue();
|
void ProcessTellQueue();
|
||||||
|
|
||||||
|
bool GetSpellFileVerified() { return spell_file_verified; }
|
||||||
|
bool GetSkillFileVerified() { return skill_file_verified; }
|
||||||
|
bool GetBaseDataFileVerified() { return base_data_file_verified; }
|
||||||
|
bool GetEQGameVerified() { return eqgame_file_verified; }
|
||||||
|
|
||||||
|
void SetSpellFileVerified(bool v) { spell_file_verified = v; }
|
||||||
|
void SetSkillFileVerified(bool v) { skill_file_verified = v; }
|
||||||
|
void SetBaseDataFileVerified(bool v) { base_data_file_verified = v; }
|
||||||
|
void SetEQGameVerified(bool v) { eqgame_file_verified = v; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearVars(bool iAll = false);
|
void ClearVars(bool iAll = false);
|
||||||
|
|
||||||
@ -128,6 +138,11 @@ private:
|
|||||||
bool pLFGMatchFilter;
|
bool pLFGMatchFilter;
|
||||||
char pLFGComments[64];
|
char pLFGComments[64];
|
||||||
|
|
||||||
|
bool spell_file_verified;
|
||||||
|
bool skill_file_verified;
|
||||||
|
bool base_data_file_verified;
|
||||||
|
bool eqgame_file_verified;
|
||||||
|
|
||||||
// Tell Queue -- really a vector :D
|
// Tell Queue -- really a vector :D
|
||||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1311,6 +1311,25 @@ bool ZoneServer::Process() {
|
|||||||
cle->ProcessTellQueue();
|
cle->ProcessTellQueue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_ClientFileStatus:
|
||||||
|
{
|
||||||
|
ServerRequestClientFileStatus *req = (ServerRequestClientFileStatus*) pack->pBuffer;
|
||||||
|
ClientListEntry *cle = client_list.FindCharacter(req->name);
|
||||||
|
|
||||||
|
if(cle) {
|
||||||
|
ServerPacket pack(ServerOP_ClientFileStatus, sizeof(ServerResponseClientFileStatus));
|
||||||
|
ServerResponseClientFileStatus *resp = (ServerResponseClientFileStatus*)pack.pBuffer;
|
||||||
|
|
||||||
|
strcpy(resp->name, req->name);
|
||||||
|
resp->spells = cle->GetSpellFileVerified();
|
||||||
|
resp->skills = cle->GetSkillFileVerified();
|
||||||
|
resp->base_data = cle->GetBaseDataFileVerified();
|
||||||
|
resp->eqgame = cle->GetEQGameVerified();
|
||||||
|
zoneserver_list.SendPacket(req->zone_id, req->instance_id, &pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Log.Out(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
Log.Out(Logs::Detail, Logs::World_Server, "Unknown ServerOPcode from zone 0x%04x, size %d", pack->opcode, pack->size);
|
||||||
|
|||||||
@ -787,6 +787,13 @@ void Client::CompleteConnect()
|
|||||||
std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
|
std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
|
||||||
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
|
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServerPacket pack(ServerOP_ClientFileStatus, sizeof(ServerRequestClientFileStatus));
|
||||||
|
ServerRequestClientFileStatus *req = (ServerRequestClientFileStatus*)pack.pBuffer;
|
||||||
|
req->zone_id = zone->GetZoneID();
|
||||||
|
req->instance_id = zone->GetInstanceID();
|
||||||
|
strn0cpy(req->name, GetName(), 64);
|
||||||
|
worldserver.SendPacket(&pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zone) {
|
if (zone) {
|
||||||
|
|||||||
@ -113,7 +113,8 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
|||||||
"EVENT_LEAVE_AREA",
|
"EVENT_LEAVE_AREA",
|
||||||
"EVENT_RESPAWN",
|
"EVENT_RESPAWN",
|
||||||
"EVENT_DEATH_COMPLETE",
|
"EVENT_DEATH_COMPLETE",
|
||||||
"EVENT_UNHANDLED_OPCODE"
|
"EVENT_UNHANDLED_OPCODE",
|
||||||
|
"EVENT_CLIENT_FILE_STATUS"
|
||||||
};
|
};
|
||||||
|
|
||||||
PerlembParser::PerlembParser() : perl(nullptr) {
|
PerlembParser::PerlembParser() : perl(nullptr) {
|
||||||
|
|||||||
@ -82,6 +82,7 @@ typedef enum {
|
|||||||
EVENT_RESPAWN,
|
EVENT_RESPAWN,
|
||||||
EVENT_DEATH_COMPLETE,
|
EVENT_DEATH_COMPLETE,
|
||||||
EVENT_UNHANDLED_OPCODE,
|
EVENT_UNHANDLED_OPCODE,
|
||||||
|
EVENT_CLIENT_FILE_STATUS,
|
||||||
|
|
||||||
_LargestEventID
|
_LargestEventID
|
||||||
} QuestEventID;
|
} QuestEventID;
|
||||||
|
|||||||
@ -1713,7 +1713,8 @@ luabind::scope lua_register_events() {
|
|||||||
luabind::value("enter_area", static_cast<int>(EVENT_ENTER_AREA)),
|
luabind::value("enter_area", static_cast<int>(EVENT_ENTER_AREA)),
|
||||||
luabind::value("leave_area", static_cast<int>(EVENT_LEAVE_AREA)),
|
luabind::value("leave_area", static_cast<int>(EVENT_LEAVE_AREA)),
|
||||||
luabind::value("death_complete", static_cast<int>(EVENT_DEATH_COMPLETE)),
|
luabind::value("death_complete", static_cast<int>(EVENT_DEATH_COMPLETE)),
|
||||||
luabind::value("unhandled_opcode", static_cast<int>(EVENT_UNHANDLED_OPCODE))
|
luabind::value("unhandled_opcode", static_cast<int>(EVENT_UNHANDLED_OPCODE)),
|
||||||
|
luabind::value("client_file_status", static_cast<int>(EVENT_CLIENT_FILE_STATUS))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -843,7 +843,11 @@ luabind::scope lua_register_packet_opcodes() {
|
|||||||
luabind::value("OpenContainer", static_cast<int>(OP_OpenContainer)),
|
luabind::value("OpenContainer", static_cast<int>(OP_OpenContainer)),
|
||||||
luabind::value("Marquee", static_cast<int>(OP_Marquee)),
|
luabind::value("Marquee", static_cast<int>(OP_Marquee)),
|
||||||
luabind::value("ClientTimeStamp", static_cast<int>(OP_ClientTimeStamp)),
|
luabind::value("ClientTimeStamp", static_cast<int>(OP_ClientTimeStamp)),
|
||||||
luabind::value("GuildPromote", static_cast<int>(OP_GuildPromote))
|
luabind::value("GuildPromote", static_cast<int>(OP_GuildPromote)),
|
||||||
|
luabind::value("World_SpellFileCheck", static_cast<int>(OP_World_SpellFileCheck)),
|
||||||
|
luabind::value("World_SkillFileCheck", static_cast<int>(OP_World_SkillFileCheck)),
|
||||||
|
luabind::value("World_BaseDataFileCheck", static_cast<int>(OP_World_BaseDataFileCheck)),
|
||||||
|
luabind::value("World_ExeFileCheck", static_cast<int>(OP_World_ExeFileCheck))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -116,7 +116,8 @@ const char *LuaEvents[_LargestEventID] = {
|
|||||||
"event_leave_area",
|
"event_leave_area",
|
||||||
"event_respawn",
|
"event_respawn",
|
||||||
"event_death_complete",
|
"event_death_complete",
|
||||||
"event_unhandled_opcode"
|
"event_unhandled_opcode",
|
||||||
|
"event_client_file_status"
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Zone *zone;
|
extern Zone *zone;
|
||||||
@ -198,6 +199,7 @@ LuaParser::LuaParser() {
|
|||||||
PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area;
|
PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area;
|
||||||
PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn;
|
PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn;
|
||||||
PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet;
|
PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet;
|
||||||
|
PlayerArgumentDispatch[EVENT_CLIENT_FILE_STATUS] = handle_player_file_status;
|
||||||
|
|
||||||
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
|
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
|
||||||
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
|
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "masterentity.h"
|
#include "masterentity.h"
|
||||||
#include "../common/seperator.h"
|
#include "../common/seperator.h"
|
||||||
#include "../common/misc_functions.h"
|
#include "../common/misc_functions.h"
|
||||||
|
#include "../common/string_util.h"
|
||||||
#include "lua_item.h"
|
#include "lua_item.h"
|
||||||
#include "lua_iteminst.h"
|
#include "lua_iteminst.h"
|
||||||
#include "lua_entity.h"
|
#include "lua_entity.h"
|
||||||
@ -501,6 +502,30 @@ void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, s
|
|||||||
lua_setfield(L, -2, "connecting");
|
lua_setfield(L, -2, "connecting");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_player_file_status(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
|
std::vector<EQEmu::Any> *extra_pointers) {
|
||||||
|
auto values = SplitString(data, ' ');
|
||||||
|
if(values.size() >= 4) {
|
||||||
|
auto spells = atoi(values[0].c_str());
|
||||||
|
auto skills = atoi(values[1].c_str());
|
||||||
|
auto basedata = atoi(values[2].c_str());
|
||||||
|
auto eqgame = atoi(values[3].c_str());
|
||||||
|
|
||||||
|
lua_pushboolean(L, spells == 1 ? true : false);
|
||||||
|
lua_setfield(L, -2, "spell_file_status");
|
||||||
|
|
||||||
|
lua_pushboolean(L, skills == 1 ? true : false);
|
||||||
|
lua_setfield(L, -2, "skills_file_status");
|
||||||
|
|
||||||
|
lua_pushboolean(L, basedata == 1 ? true : false);
|
||||||
|
lua_setfield(L, -2, "base_data_file_status");
|
||||||
|
|
||||||
|
lua_pushboolean(L, eqgame == 1 ? true : false);
|
||||||
|
lua_setfield(L, -2, "eqgame_file_status");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
std::vector<EQEmu::Any> *extra_pointers) {
|
std::vector<EQEmu::Any> *extra_pointers) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,6 +93,8 @@ void handle_player_respawn(QuestInterface *parse, lua_State* L, Client* client,
|
|||||||
std::vector<EQEmu::Any> *extra_pointers);
|
std::vector<EQEmu::Any> *extra_pointers);
|
||||||
void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
std::vector<EQEmu::Any> *extra_pointers);
|
std::vector<EQEmu::Any> *extra_pointers);
|
||||||
|
void handle_player_file_status(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
|
std::vector<EQEmu::Any> *extra_pointers);
|
||||||
void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
std::vector<EQEmu::Any> *extra_pointers);
|
std::vector<EQEmu::Any> *extra_pointers);
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@
|
|||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
#include "zone_config.h"
|
#include "zone_config.h"
|
||||||
|
#include "quest_parser_collection.h"
|
||||||
|
|
||||||
extern EntityList entity_list;
|
extern EntityList entity_list;
|
||||||
extern Zone* zone;
|
extern Zone* zone;
|
||||||
@ -1841,6 +1841,20 @@ void WorldServer::Process() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_ClientFileStatus:
|
||||||
|
{
|
||||||
|
ServerResponseClientFileStatus *resp = (ServerResponseClientFileStatus*)pack->pBuffer;
|
||||||
|
Client* client = entity_list.GetClientByName(resp->name);
|
||||||
|
if(client) {
|
||||||
|
parse->EventPlayer(EVENT_CLIENT_FILE_STATUS, client, StringFormat("%d %d %d %d",
|
||||||
|
resp->spells ? 1 : 0,
|
||||||
|
resp->skills ? 1 : 0,
|
||||||
|
resp->base_data ? 1 : 0,
|
||||||
|
resp->eqgame ? 1 : 0).c_str(), 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
std::cout << " Unknown ZSopcode:" << (int)pack->opcode;
|
std::cout << " Unknown ZSopcode:" << (int)pack->opcode;
|
||||||
std::cout << " size:" << pack->size << std::endl;
|
std::cout << " size:" << pack->size << std::endl;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user