Merge branches 'lsid' and 'master' of https://github.com/EQEmu/Server into lsid

This commit is contained in:
Akkadius
2019-08-10 03:26:40 -05:00
46 changed files with 1857 additions and 558 deletions
+1 -1
View File
@@ -489,7 +489,7 @@ void Client::ResetAA() {
database.DeleteCharacterLeadershipAAs(CharacterID());
// undefined for these clients
if (ClientVersionBit() & EQEmu::versions::maskTitaniumAndEarlier)
Kick();
Kick("AA Reset on client that doesn't support it");
}
void Client::SendClearAA()
+23 -3
View File
@@ -136,6 +136,7 @@ Client::Client(EQStreamInterface* ieqs)
forget_timer(0),
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
tribute_timer(Tribute_duration),
proximity_timer(ClientProximity_interval),
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
@@ -446,7 +447,7 @@ Client::~Client() {
numclients--;
UpdateWindowTitle();
if(zone)
zone->RemoveAuth(GetName());
zone->RemoveAuth(GetName(), lskey);
//let the stream factory know were done with this stream
eqs->Close();
@@ -845,7 +846,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
{
if(AttemptedMessages > RuleI(Chat, MaxMessagesBeforeKick))
{
Kick();
Kick("Sent too many chat messages at once.");
return;
}
if(GlobalChatLimiterTimer)
@@ -2586,13 +2587,19 @@ void Client::SetPVP(bool toggle, bool message) {
Save();
}
void Client::Kick(const std::string &reason) {
client_state = CLIENT_KICKED;
Log(Logs::General, Logs::Client_Login, "Client [%s] kicked, reason [%s]", GetCleanName(), reason.c_str());
}
void Client::WorldKick() {
auto outapp = new EQApplicationPacket(OP_GMKick, sizeof(GMKick_Struct));
GMKick_Struct* gmk = (GMKick_Struct *)outapp->pBuffer;
strcpy(gmk->name,GetName());
QueuePacket(outapp);
safe_delete(outapp);
Kick();
Kick("World kick issued");
}
void Client::GMKill() {
@@ -9115,3 +9122,16 @@ bool Client::GotoPlayer(std::string player_name)
return false;
}
glm::vec4 &Client::GetLastPositionBeforeBulkUpdate()
{
return last_position_before_bulk_update;
}
/**
* @param in_last_position_before_bulk_update
*/
void Client::SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update)
{
Client::last_position_before_bulk_update = in_last_position_before_bulk_update;
}
+6 -1
View File
@@ -371,9 +371,9 @@ public:
inline bool ClientDataLoaded() const { return client_data_loaded; }
inline bool Connected() const { return (client_state == CLIENT_CONNECTED); }
inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); }
inline void Kick() { client_state = CLIENT_KICKED; }
inline void Disconnect() { eqs->Close(); client_state = DISCONNECTED; }
inline bool IsLD() const { return (bool) (client_state == CLIENT_LINKDEAD); }
void Kick(const std::string &reason);
void WorldKick();
inline uint8 GetAnon() const { return m_pp.anon; }
inline PlayerProfile_Struct& GetPP() { return m_pp; }
@@ -1309,6 +1309,9 @@ public:
uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns.
void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update);
glm::vec4 &GetLastPositionBeforeBulkUpdate();
protected:
friend class Mob;
void CalcItemBonuses(StatBonuses* newbon);
@@ -1518,6 +1521,7 @@ private:
Timer forget_timer; // our 2 min everybody forgets you timer
Timer autosave_timer;
Timer client_scan_npc_aggro_timer;
Timer client_zone_wide_full_position_update_timer;
Timer tribute_timer;
Timer proximity_timer;
@@ -1540,6 +1544,7 @@ private:
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
glm::vec3 m_Proximity;
glm::vec4 last_position_before_bulk_update;
void BulkSendInventoryItems();
+57 -12
View File
@@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "water_map.h"
#include "worldserver.h"
#include "zone.h"
#include "mob_movement_manager.h"
#ifdef BOTS
#include "bot.h"
@@ -805,6 +806,8 @@ void Client::CompleteConnect()
parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0);
SetLastPositionBeforeBulkUpdate(GetPosition());
/* This sub event is for if a player logs in for the first time since entering world. */
if (firstlogon == 1) {
parse->EventPlayer(EVENT_CONNECT, this, "", 0);
@@ -1166,13 +1169,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
*/
Client* client = entity_list.GetClientByName(cze->char_name);
if (!zone->GetAuth(ip, cze->char_name, &WID, &account_id, &character_id, &admin, lskey, &tellsoff)) {
Log(Logs::General, Logs::Error, "GetAuth() returned false kicking client");
if (client != 0) {
Log(Logs::General, Logs::Client_Login, "%s failed zone auth check.", cze->char_name);
if (nullptr != client) {
client->Save();
client->Kick();
client->Kick("Failed auth check");
}
//ret = false; // TODO: Can we tell the client to get lost in a good way
client_state = CLIENT_KICKED;
return;
}
@@ -1682,7 +1683,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/**
* DevTools Load Settings
*/
if (Admin() >= 200) {
if (Admin() >= EQEmu::DevTools::GM_ACCOUNT_STATUS_LEVEL) {
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID());
if (DataBucket::GetData(dev_tools_window_key) == "true") {
dev_tools_window_enabled = false;
@@ -4467,16 +4468,16 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
/* Handle client aggro scanning timers NPCs */
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
if (is_client_moving) {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
client_scan_npc_aggro_timer.Disable();
client_scan_npc_aggro_timer.Start(500);
}
} else {
}
else {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
@@ -4484,7 +4485,51 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
client_scan_npc_aggro_timer.Start(3000);
}
}
/**
* On a normal basis we limit mob movement updates based on distance
* This ensures we send a periodic full zone update to a client that has started moving after 5 or so minutes
*
* For very large zones we will also force a full update based on distance
*
* We ignore a small distance around us so that we don't interrupt already pathing deltas as those npcs will appear
* to full stop when they are actually still pathing
*/
float distance_moved = DistanceNoZ(GetLastPositionBeforeBulkUpdate(), GetPosition());
bool moved_far_enough_before_bulk_update = distance_moved >= zone->GetNpcPositionUpdateDistance();
bool is_ready_to_update = (
client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update
);
if (is_client_moving && is_ready_to_update) {
Log(Logs::Detail, Logs::Normal, "[%s] Client Zone Wide Position Update NPCs", GetCleanName());
auto &mob_movement_manager = MobMovementManager::Get();
auto &mob_list = entity_list.GetMobList();
for (auto &it : mob_list) {
Mob *entity = it.second;
if (!entity->IsNPC()) {
continue;
}
int animation_speed = 0;
if (entity->IsMoving()) {
if (entity->IsRunning()) {
animation_speed = (entity->IsFeared() ? entity->GetFearSpeed() : entity->GetRunspeed());
}
else {
animation_speed = entity->GetWalkspeed();
}
}
mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, animation_speed, ClientRangeAny, this);
}
SetLastPositionBeforeBulkUpdate(GetPosition());
}
float new_heading = EQ12toFloat(ppu->heading);
int32 new_animation = ppu->animation;
@@ -9757,7 +9802,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
casting_spell_id);
database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName());
safe_delete_array(detect);
Kick(); // Kick client to prevent client and server from getting out-of-sync inventory slots
Kick("Inventory desync"); // Kick client to prevent client and server from getting out-of-sync inventory slots
return;
}
}
@@ -9801,7 +9846,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
void Client::Handle_OP_MoveMultipleItems(const EQApplicationPacket *app)
{
Kick(); // TODO: lets not desync though
Kick("Unimplemented move multiple items"); // TODO: lets not desync though
}
void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app)
+3 -2
View File
@@ -591,8 +591,8 @@ bool Client::Process() {
// only if client is not feigned
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
int npc_scan_count = 0;
for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) {
Mob *mob = it->first;
for (auto & close_mob : close_mobs) {
Mob *mob = close_mob.first;
if (!mob)
continue;
@@ -603,6 +603,7 @@ bool Client::Process() {
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
mob->AddToHateList(this, 25);
}
npc_scan_count++;
}
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
+4 -4
View File
@@ -1912,7 +1912,7 @@ void command_permaclass(Client *c, const Seperator *sep)
Log(Logs::General, Logs::Normal, "Class change request from %s for %s, requested class:%i", c->GetName(), t->GetName(), atoi(sep->arg[1]) );
t->SetBaseClass(atoi(sep->arg[1]));
t->Save();
t->Kick();
t->Kick("Class was changed.");
}
}
@@ -3904,7 +3904,7 @@ void command_kick(Client *c, const Seperator *sep)
client->Message(0, "You have been kicked by %s", c->GetName());
auto outapp = new EQApplicationPacket(OP_GMKick, 0);
client->QueuePacket(outapp);
client->Kick();
client->Kick("Ordered kicked by command");
c->Message(0, "Kick: local: kicking %s", sep->arg[1]);
}
}
@@ -4499,7 +4499,7 @@ void command_gmzone(Client *c, const Seperator *sep)
identifier = sep->arg[3];
}
std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str());
std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, identifier.c_str(), zone_version);
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
if (existing_zone_instance.length() > 0) {
@@ -5196,7 +5196,7 @@ void command_name(Client *c, const Seperator *sep)
c->Message(0, "Successfully renamed %s to %s", oldname, sep->arg[1]);
// until we get the name packet working right this will work
c->Message(0, "Sending player to char select.");
target->Kick();
target->Kick("Name was changed");
}
else
c->Message(13, "ERROR: Unable to rename %s. Check that the new name '%s' isn't already taken.", oldname, sep->arg[2]);
+12
View File
@@ -1713,6 +1713,18 @@ Client *EntityList::GetClientByWID(uint32 iWID)
return nullptr;
}
Client *EntityList::GetClientByLSID(uint32 iLSID)
{
auto it = client_list.begin();
while (it != client_list.end()) {
if (it->second->LSAccountID() == iLSID) {
return it->second;
}
++it;
}
return nullptr;
}
Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient)
{
std::vector<Client *> ClientsInRange;
+1
View File
@@ -176,6 +176,7 @@ public:
}
Client *GetClientByCharID(uint32 iCharID);
Client *GetClientByWID(uint32 iWID);
Client *GetClientByLSID(uint32 iLSID);
Client *GetClient(uint32 ip, uint16 port);
Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr);
Group *GetGroupByMob(Mob* mob);
+2 -2
View File
@@ -1608,7 +1608,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
banker ? banker->GetName() : "UNKNOWN NPC", distance);
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
safe_delete_array(hacked_string);
Kick(); // Kicking player to avoid item loss do to client and server inventories not being sync'd
Kick("Inventory desync"); // Kicking player to avoid item loss do to client and server inventories not being sync'd
return false;
}
}
@@ -1822,7 +1822,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
// Step 4: Check for entity trade
if (dst_slot_id >= EQEmu::invslot::TRADE_BEGIN && dst_slot_id <= EQEmu::invslot::TRADE_END) {
if (src_slot_id != EQEmu::invslot::slotCursor) {
Kick();
Kick("Trade with non-cursor item");
return false;
}
if (with) {
+1 -1
View File
@@ -47,7 +47,7 @@ bool Lua_Client::InZone() {
void Lua_Client::Kick() {
Lua_Safe_Call_Void();
self->Kick();
self->Kick("Lua Quest");
}
void Lua_Client::Disconnect() {
+4 -1
View File
@@ -1128,7 +1128,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
UpdateActiveLight();
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
if (IsNPC() && race == ERUDITE)
ns->spawn.showhelm = 1;
else
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
ns->spawn.NPC = IsClient() ? 0 : 1;
File diff suppressed because it is too large Load Diff
+27 -16
View File
@@ -41,18 +41,29 @@ class MobMovementManager
public:
~MobMovementManager();
void Process();
void AddMob(Mob *m);
void RemoveMob(Mob *m);
void AddClient(Client *c);
void RemoveClient(Client *c);
void AddMob(Mob *mob);
void RemoveMob(Mob *mob);
void AddClient(Client *client);
void RemoveClient(Client *client);
void RotateTo(Mob *who, float to, MobMovementMode mode = MovementRunning);
void RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode = MovementRunning);
void Teleport(Mob *who, float x, float y, float z, float heading);
void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
void StopNavigation(Mob *who);
void SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range);
void SendCommandToClients(
Mob *mob,
float delta_x,
float delta_y,
float delta_z,
float delta_heading,
int anim,
ClientRange range,
Client* single_client = nullptr
);
float FixHeading(float in);
void DumpStats(Client *to);
void DumpStats(Client *client);
void ClearStats();
static MobMovementManager &Get() {
@@ -65,18 +76,18 @@ private:
MobMovementManager(const MobMovementManager&);
MobMovementManager& operator=(const MobMovementManager&);
void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode);
void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim);
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode);
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode);
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode);
void PushStopMoving(MobMovementEntry &ent);
void PushEvadeCombat(MobMovementEntry &ent);
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode);
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
void PushStopMoving(MobMovementEntry &mob_movement_entry);
void PushEvadeCombat(MobMovementEntry &mob_movement_entry);
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
struct Implementation;
std::unique_ptr<Implementation> _impl;
+1 -1
View File
@@ -174,7 +174,7 @@ XS(XS_Client_Kick) {
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->Kick();
THIS->Kick("Perl Quest");
}
XSRETURN_EMPTY;
}
+4 -4
View File
@@ -809,7 +809,7 @@ void QuestManager::changedeity(int diety_id) {
initiator->SetDeity(diety_id);
initiator->Message(15,"Your Deity has been changed/set to: %i", diety_id);
initiator->Save(1);
initiator->Kick();
initiator->Kick("Deity change by QuestManager");
}
else
{
@@ -943,7 +943,7 @@ void QuestManager::permaclass(int class_id) {
//Makes the client the class specified
initiator->SetBaseClass(class_id);
initiator->Save(2);
initiator->Kick();
initiator->Kick("Base class change by QuestManager");
}
void QuestManager::permarace(int race_id) {
@@ -951,7 +951,7 @@ void QuestManager::permarace(int race_id) {
//Makes the client the race specified
initiator->SetBaseRace(race_id);
initiator->Save(2);
initiator->Kick();
initiator->Kick("Base race change by QuestManager");
}
void QuestManager::permagender(int gender_id) {
@@ -959,7 +959,7 @@ void QuestManager::permagender(int gender_id) {
//Makes the client the gender specified
initiator->SetBaseGender(gender_id);
initiator->Save(2);
initiator->Kick();
initiator->Kick("Base gender change by QuestManager");
}
uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
+2 -1
View File
@@ -298,7 +298,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
if(IsClient()) {
char temp[64];
sprintf(temp, "%d", spell_id);
parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0);
if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0) != 0)
return false;
} else if(IsNPC()) {
char temp[64];
sprintf(temp, "%d", spell_id);
+2 -2
View File
@@ -112,7 +112,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) {
// (it just didn't handle partial stack move actions)
if (stack_size > 0) {
if (!inst->IsStackable() || !inst2 || !inst2->GetItem() || (inst->GetID() != inst2->GetID()) || (stack_size > inst->GetCharges())) {
client->Kick();
client->Kick("Error stacking item in trade");
return;
}
@@ -138,7 +138,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) {
}
else {
if (inst2 && inst2->GetID()) {
client->Kick();
client->Kick("Attempting to add null item to trade");
return;
}
+25
View File
@@ -534,7 +534,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
ServerZoneIncomingClient_Struct* szic = (ServerZoneIncomingClient_Struct*)pack->pBuffer;
if (is_zone_loaded) {
SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
if (szic->zoneid == zone->GetZoneID()) {
auto client = entity_list.GetClientByLSID(szic->lsid);
if (client) {
client->Kick("Dropped by world CLE subsystem");
client->Save();
}
zone->RemoveAuth(szic->lsid);
zone->AddAuth(szic);
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
@@ -547,6 +555,23 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_DropClient: {
if (pack->size != sizeof(ServerZoneDropClient_Struct)) {
break;
}
ServerZoneDropClient_Struct* drop = (ServerZoneDropClient_Struct*)pack->pBuffer;
if (zone) {
zone->RemoveAuth(drop->lsid);
auto client = entity_list.GetClientByLSID(drop->lsid);
if (client) {
client->Kick("Dropped by world CLE subsystem");
client->Save();
}
}
break;
}
case ServerOP_ZonePlayer: {
ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*)pack->pBuffer;
Client* client = entity_list.GetClientByName(szp->name);
+87 -7
View File
@@ -55,6 +55,7 @@
#include "zone_config.h"
#include "mob_movement_manager.h"
#include "npc_scale_manager.h"
#include "../common/data_verification.h"
#include <time.h>
#include <ctime>
@@ -864,6 +865,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
m_last_ucss_update = 0;
mMovementManager = &MobMovementManager::Get();
SetNpcPositionUpdateDistance(0);
}
Zone::~Zone() {
@@ -1106,6 +1109,7 @@ void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
zca->accid = szic->accid;
zca->admin = szic->admin;
zca->charid = szic->charid;
zca->lsid = szic->lsid;
zca->tellsoff = szic->tellsoff;
strn0cpy(zca->charname, szic->charname, sizeof(zca->charname));
strn0cpy(zca->lskey, szic->lskey, sizeof(zca->lskey));
@@ -1113,16 +1117,31 @@ void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
client_auth_list.Insert(zca);
}
void Zone::RemoveAuth(const char* iCharName)
void Zone::RemoveAuth(const char* iCharName, const char* iLSKey)
{
LinkedListIterator<ZoneClientAuth_Struct*> iterator(client_auth_list);
iterator.Reset();
while (iterator.MoreElements()) {
ZoneClientAuth_Struct* zca = iterator.GetData();
if (strcasecmp(zca->charname, iCharName) == 0) {
iterator.RemoveCurrent();
return;
if (strcasecmp(zca->charname, iCharName) == 0 && strcasecmp(zca->lskey, iLSKey) == 0) {
iterator.RemoveCurrent();
return;
}
iterator.Advance();
}
}
void Zone::RemoveAuth(uint32 lsid)
{
LinkedListIterator<ZoneClientAuth_Struct*> iterator(client_auth_list);
iterator.Reset();
while (iterator.MoreElements()) {
ZoneClientAuth_Struct* zca = iterator.GetData();
if (zca->lsid == lsid) {
iterator.RemoveCurrent();
continue;
}
iterator.Advance();
}
@@ -1178,9 +1197,9 @@ uint32 Zone::CountAuth() {
bool Zone::Process() {
spawn_conditions.Process();
if(spawn2_timer.Check()) {
if (spawn2_timer.Check()) {
LinkedListIterator<Spawn2*> iterator(spawn2_list);
LinkedListIterator<Spawn2 *> iterator(spawn2_list);
EQEmu::InventoryProfile::CleanDirty();
@@ -1196,10 +1215,15 @@ bool Zone::Process() {
}
}
if(adv_data && !did_adventure_actions)
if (adv_data && !did_adventure_actions) {
DoAdventureActions();
}
if (GetNpcPositionUpdateDistance() == 0) {
CalculateNpcUpdateDistanceSpread();
}
}
if(initgrids_timer.Check()) {
//delayed grid loading stuff.
initgrids_timer.Disable();
@@ -2349,3 +2373,59 @@ void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
if (m_last_ucss_update < update_timestamp)
m_ucss_available = ucss_available;
}
int Zone::GetNpcPositionUpdateDistance() const
{
return npc_position_update_distance;
}
void Zone::SetNpcPositionUpdateDistance(int in_npc_position_update_distance)
{
Zone::npc_position_update_distance = in_npc_position_update_distance;
}
void Zone::CalculateNpcUpdateDistanceSpread()
{
float max_x = 0;
float max_y = 0;
float min_x = 0;
float min_y = 0;
auto &mob_list = entity_list.GetMobList();
for (auto &it : mob_list) {
Mob *entity = it.second;
if (!entity->IsNPC()) {
continue;
}
if (entity->GetX() <= min_x) {
min_x = entity->GetX();
}
if (entity->GetY() <= min_y) {
min_y = entity->GetY();
}
if (entity->GetX() >= max_x) {
max_x = entity->GetX();
}
if (entity->GetY() >= max_y) {
max_y = entity->GetY();
}
}
int x_spread = int(abs(max_x - min_x));
int y_spread = int(abs(max_y - min_y));
int combined_spread = int(abs((x_spread + y_spread) / 2));
int update_distance = EQEmu::ClampLower(int(combined_spread / 4), int(zone->GetMaxMovementUpdateRange()));
SetNpcPositionUpdateDistance(update_distance);
Log(Logs::General, Logs::Debug,
"NPC update spread distance set to [%i] combined_spread [%i]",
update_distance,
combined_spread
);
}
+9 -2
View File
@@ -52,6 +52,7 @@ struct ZoneClientAuth_Struct {
uint32 accid;
int16 admin;
uint32 charid;
uint32 lsid;
bool tellsoff;
char charname[64];
char lskey[30];
@@ -125,6 +126,9 @@ public:
bool Process();
bool SaveZoneCFG();
int GetNpcPositionUpdateDistance() const;
void SetNpcPositionUpdateDistance(int in_npc_position_update_distance);
char *adv_data;
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
@@ -218,6 +222,7 @@ public:
void ChangeWeather();
void ClearBlockedSpells();
void ClearNPCTypeCache(int id);
void CalculateNpcUpdateDistanceSpread();
void DelAggroMob() { aggroedmobs--; }
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
void Despawn(uint32 spawngroupID);
@@ -243,7 +248,8 @@ public:
void LoadZoneDoors(const char *zone, int16 version);
void ReloadStaticData();
void ReloadWorld(uint32 Option);
void RemoveAuth(const char *iCharName);
void RemoveAuth(const char *iCharName, const char *iLSKey);
void RemoveAuth(uint32 lsid);
void Repop(uint32 delay = 0);
void RepopClose(const glm::vec4 &client_position, uint32 repop_distance);
void RequestUCSServerStatus();
@@ -288,7 +294,7 @@ public:
*/
find_replace(message, std::string("%"), std::string("."));
if (message.find("\n") != std::string::npos) {
if (message.find('\n') != std::string::npos) {
auto message_split = SplitString(message, '\n');
entity_list.MessageStatus(
0,
@@ -343,6 +349,7 @@ private:
glm::vec4 m_Graveyard;
int default_ruleset;
int totalBS;
int npc_position_update_distance;
int32 aggroedmobs;
uint8 zone_type;
uint16 instanceversion;