Change eqstream interface to get rid of some stuff as well as flesh out a few more options plus some rule and performance changes

This commit is contained in:
KimLS 2019-03-13 22:55:49 -07:00
parent 67b228a91c
commit 7977949ae9
21 changed files with 227 additions and 181 deletions

View File

@ -19,6 +19,47 @@ typedef enum {
class EQApplicationPacket; class EQApplicationPacket;
class OpcodeManager; class OpcodeManager;
struct EQStreamManagerInterfaceOptions
{
EQStreamManagerInterfaceOptions() {
opcode_size = 2;
}
EQStreamManagerInterfaceOptions(int port, bool encoded, bool compressed) {
opcode_size = 2;
track_opcode_stats = false;
//World seems to support both compression and xor zone supports one or the others.
//Enforce one or the other in the convienence construct
//Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that.
if (compressed) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression;
}
else if (encoded) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeXOR;
}
daybreak_options.port = port;
}
int opcode_size;
bool track_opcode_stats;
EQ::Net::DaybreakConnectionManagerOptions daybreak_options;
};
class EQStreamManagerInterface
{
public:
EQStreamManagerInterface(const EQStreamManagerInterfaceOptions &options) { m_options = options; }
virtual ~EQStreamManagerInterface() { };
const EQStreamManagerInterfaceOptions& GetOptions() const { return m_options; }
EQStreamManagerInterfaceOptions& MutateOptions() { return m_options; }
protected:
EQStreamManagerInterfaceOptions m_options;
};
class EQStreamInterface { class EQStreamInterface {
public: public:
virtual ~EQStreamInterface() {} virtual ~EQStreamInterface() {}
@ -60,8 +101,9 @@ public:
virtual EQStreamState GetState() = 0; virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 0; virtual void SetOpcodeManager(OpcodeManager **opm) = 0;
virtual const EQEmu::versions::ClientVersion ClientVersion() const { return EQEmu::versions::ClientVersion::Unknown; } virtual const EQEmu::versions::ClientVersion ClientVersion() const { return EQEmu::versions::ClientVersion::Unknown; }
virtual std::shared_ptr<EQ::Net::DaybreakConnection> GetRawConnection() const = 0;
virtual Stats GetStats() const = 0; virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0;
virtual EQStreamManagerInterface* GetManager() const = 0;
}; };
#endif /*EQSTREAMINTF_H_*/ #endif /*EQSTREAMINTF_H_*/

View File

@ -90,15 +90,21 @@ void EQStreamProxy::RemoveData() {
m_stream->RemoveData(); m_stream->RemoveData();
} }
std::shared_ptr<EQ::Net::DaybreakConnection> EQStreamProxy::GetRawConnection() const {
return m_stream->GetRawConnection();
}
EQStreamInterface::Stats EQStreamProxy::GetStats() const EQStreamInterface::Stats EQStreamProxy::GetStats() const
{ {
return m_stream->GetStats(); return m_stream->GetStats();
} }
void EQStreamProxy::ResetStats()
{
m_stream->ResetStats();
}
EQStreamManagerInterface *EQStreamProxy::GetManager() const
{
return m_stream->GetManager();
}
bool EQStreamProxy::CheckState(EQStreamState state) { bool EQStreamProxy::CheckState(EQStreamState state) {
if(m_stream) if(m_stream)
return(m_stream->CheckState(state)); return(m_stream->CheckState(state));

View File

@ -31,8 +31,9 @@ public:
virtual const EQEmu::versions::ClientVersion ClientVersion() const; virtual const EQEmu::versions::ClientVersion ClientVersion() const;
virtual EQStreamState GetState(); virtual EQStreamState GetState();
virtual void SetOpcodeManager(OpcodeManager **opm); virtual void SetOpcodeManager(OpcodeManager **opm);
virtual std::shared_ptr<EQ::Net::DaybreakConnection> GetRawConnection() const;
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const;
protected: protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object. std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.

View File

@ -244,7 +244,7 @@ namespace EQ
encode_passes[0] = DaybreakEncodeType::EncodeNone; encode_passes[0] = DaybreakEncodeType::EncodeNone;
encode_passes[1] = DaybreakEncodeType::EncodeNone; encode_passes[1] = DaybreakEncodeType::EncodeNone;
port = 0; port = 0;
hold_size = 448; hold_size = 512;
hold_length_ms = 50; hold_length_ms = 50;
simulated_in_packet_loss = 0; simulated_in_packet_loss = 0;
simulated_out_packet_loss = 0; simulated_out_packet_loss = 0;

View File

@ -2,10 +2,8 @@
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../eqemu_logsys_fmt.h" #include "../eqemu_logsys_fmt.h"
EQ::Net::EQStreamManager::EQStreamManager(EQStreamManagerOptions &options) : m_daybreak(options.daybreak_options) EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_daybreak(options.daybreak_options)
{ {
m_options = options;
m_daybreak.OnNewConnection(std::bind(&EQStreamManager::DaybreakNewConnection, this, std::placeholders::_1)); m_daybreak.OnNewConnection(std::bind(&EQStreamManager::DaybreakNewConnection, this, std::placeholders::_1));
m_daybreak.OnConnectionStateChange(std::bind(&EQStreamManager::DaybreakConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); m_daybreak.OnConnectionStateChange(std::bind(&EQStreamManager::DaybreakConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_daybreak.OnPacketRecv(std::bind(&EQStreamManager::DaybreakPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); m_daybreak.OnPacketRecv(std::bind(&EQStreamManager::DaybreakPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
@ -49,7 +47,7 @@ void EQ::Net::EQStreamManager::DaybreakPacketRecv(std::shared_ptr<DaybreakConnec
} }
} }
EQ::Net::EQStream::EQStream(EQStreamManager *owner, std::shared_ptr<DaybreakConnection> connection) EQ::Net::EQStream::EQStream(EQStreamManagerInterface *owner, std::shared_ptr<DaybreakConnection> connection)
{ {
m_owner = owner; m_owner = owner;
m_connection = connection; m_connection = connection;
@ -67,14 +65,14 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
opcode = p->GetOpcodeBypass(); opcode = p->GetOpcodeBypass();
} }
else { else {
if (m_owner->m_options.track_opcode_stats) { if (m_owner->GetOptions().track_opcode_stats) {
m_packet_sent_count[p->GetOpcode()]++; //Wont bother with bypass tracking of these since those are rare for testing anyway m_packet_sent_count[p->GetOpcode()]++; //Wont bother with bypass tracking of these since those are rare for testing anyway
} }
opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode()); opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode());
} }
EQ::Net::DynamicPacket out; EQ::Net::DynamicPacket out;
switch (m_owner->m_options.opcode_size) { switch (m_owner->GetOptions().opcode_size) {
case 1: case 1:
out.PutUInt8(0, opcode); out.PutUInt8(0, opcode);
out.PutData(1, p->pBuffer, p->size); out.PutData(1, p->pBuffer, p->size);
@ -109,7 +107,7 @@ EQApplicationPacket *EQ::Net::EQStream::PopPacket() {
auto &p = m_packet_queue.front(); auto &p = m_packet_queue.front();
uint16 opcode = 0; uint16 opcode = 0;
switch (m_owner->m_options.opcode_size) { switch (m_owner->GetOptions().opcode_size) {
case 1: case 1:
opcode = p->GetUInt8(0); opcode = p->GetUInt8(0);
break; break;
@ -119,11 +117,11 @@ EQApplicationPacket *EQ::Net::EQStream::PopPacket() {
} }
EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode); EmuOpcode emu_op = (*m_opcode_manager)->EQToEmu(opcode);
if (m_owner->m_options.track_opcode_stats) { if (m_owner->GetOptions().track_opcode_stats) {
m_packet_recv_count[emu_op]++; m_packet_recv_count[emu_op]++;
} }
EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->m_options.opcode_size, p->Length() - m_owner->m_options.opcode_size); EQApplicationPacket *ret = new EQApplicationPacket(emu_op, (unsigned char*)p->Data() + m_owner->GetOptions().opcode_size, p->Length() - m_owner->GetOptions().opcode_size);
ret->SetProtocolOpcode(opcode); ret->SetProtocolOpcode(opcode);
m_packet_queue.pop_front(); m_packet_queue.pop_front();
return ret; return ret;
@ -138,11 +136,11 @@ void EQ::Net::EQStream::Close() {
std::string EQ::Net::EQStream::GetRemoteAddr() const std::string EQ::Net::EQStream::GetRemoteAddr() const
{ {
return GetRawConnection()->RemoteEndpoint(); return m_connection->RemoteEndpoint();
} }
uint32 EQ::Net::EQStream::GetRemoteIP() const { uint32 EQ::Net::EQStream::GetRemoteIP() const {
return inet_addr(GetRawConnection()->RemoteEndpoint().c_str()); return inet_addr(m_connection->RemoteEndpoint().c_str());
} }
bool EQ::Net::EQStream::CheckState(EQStreamState state) { bool EQ::Net::EQStream::CheckState(EQStreamState state) {
@ -153,8 +151,8 @@ EQStreamInterface::MatchState EQ::Net::EQStream::CheckSignature(const Signature
if (!m_packet_queue.empty()) { if (!m_packet_queue.empty()) {
auto p = m_packet_queue.front().get(); auto p = m_packet_queue.front().get();
uint16 opcode = 0; uint16 opcode = 0;
size_t length = p->Length() - m_owner->m_options.opcode_size; size_t length = p->Length() - m_owner->GetOptions().opcode_size;
switch (m_owner->m_options.opcode_size) { switch (m_owner->GetOptions().opcode_size) {
case 1: case 1:
opcode = p->GetUInt8(0); opcode = p->GetUInt8(0);
break; break;
@ -167,8 +165,8 @@ EQStreamInterface::MatchState EQ::Net::EQStream::CheckSignature(const Signature
if (m_packet_queue.size() > 1) { if (m_packet_queue.size() > 1) {
p = m_packet_queue[1].get(); p = m_packet_queue[1].get();
opcode = 0; opcode = 0;
length = p->Length() - m_owner->m_options.opcode_size; length = p->Length() - m_owner->GetOptions().opcode_size;
switch (m_owner->m_options.opcode_size) { switch (m_owner->GetOptions().opcode_size) {
case 1: case 1:
opcode = p->GetUInt8(0); opcode = p->GetUInt8(0);
break; break;
@ -185,23 +183,23 @@ EQStreamInterface::MatchState EQ::Net::EQStream::CheckSignature(const Signature
if (opcode == sig->first_eq_opcode) { if (opcode == sig->first_eq_opcode) {
if (length == sig->first_length) { if (length == sig->first_length) {
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length matched {3}", LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length matched {3}",
GetRawConnection()->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length); m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length);
return MatchSuccessful; return MatchSuccessful;
} }
else if (length == 0) { else if (length == 0) {
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length is ignored.", LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} and length is ignored.",
GetRawConnection()->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode); m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode);
return MatchSuccessful; return MatchSuccessful;
} }
else { else {
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} but length {3} did not match expected {4}", LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode matched {2:#x} but length {3} did not match expected {4}",
GetRawConnection()->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length, sig->first_length); m_connection->RemoteEndpoint(), m_connection->RemotePort(), sig->first_eq_opcode, length, sig->first_length);
return MatchFailed; return MatchFailed;
} }
} }
else { else {
LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode {1:#x} did not match expected {2:#x}", LogF(Logs::General, Logs::Netcode, "[IDENT_TRACE] {0}:{1}: First opcode {1:#x} did not match expected {2:#x}",
GetRawConnection()->RemoteEndpoint(), m_connection->RemotePort(), opcode, sig->first_eq_opcode); m_connection->RemoteEndpoint(), m_connection->RemotePort(), opcode, sig->first_eq_opcode);
return MatchFailed; return MatchFailed;
} }
} }
@ -243,3 +241,13 @@ EQ::Net::EQStream::Stats EQ::Net::EQStream::GetStats() const
return ret; return ret;
} }
void EQ::Net::EQStream::ResetStats()
{
m_connection->ResetStats();
}
EQStreamManagerInterface *EQ::Net::EQStream::GetManager() const
{
return m_owner;
}

View File

@ -12,46 +12,16 @@ namespace EQ
{ {
namespace Net namespace Net
{ {
struct EQStreamManagerOptions
{
EQStreamManagerOptions() {
opcode_size = 2;
}
EQStreamManagerOptions(int port, bool encoded, bool compressed) {
opcode_size = 2;
track_opcode_stats = false;
//World seems to support both compression and xor zone supports one or the others.
//Enforce one or the other in the convienence construct
//Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that.
if (compressed) {
daybreak_options.encode_passes[0] = EncodeCompression;
}
else if (encoded) {
daybreak_options.encode_passes[0] = EncodeXOR;
}
daybreak_options.port = port;
}
int opcode_size;
bool track_opcode_stats;
DaybreakConnectionManagerOptions daybreak_options;
};
class EQStream; class EQStream;
class EQStreamManager class EQStreamManager : public EQStreamManagerInterface
{ {
public: public:
EQStreamManager(EQStreamManagerOptions &options); EQStreamManager(const EQStreamManagerInterfaceOptions &options);
~EQStreamManager(); ~EQStreamManager();
void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; } void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; }
void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; } void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
private: private:
EQStreamManagerOptions m_options;
DaybreakConnectionManager m_daybreak; DaybreakConnectionManager m_daybreak;
std::function<void(std::shared_ptr<EQStream>)> m_on_new_connection; std::function<void(std::shared_ptr<EQStream>)> m_on_new_connection;
std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change; std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
@ -66,7 +36,7 @@ namespace EQ
class EQStream : public EQStreamInterface class EQStream : public EQStreamInterface
{ {
public: public:
EQStream(EQStreamManager *parent, std::shared_ptr<DaybreakConnection> connection); EQStream(EQStreamManagerInterface *parent, std::shared_ptr<DaybreakConnection> connection);
~EQStream(); ~EQStream();
virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req = true); virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req = true);
@ -87,13 +57,11 @@ namespace EQ
m_opcode_manager = opm; m_opcode_manager = opm;
} }
virtual std::shared_ptr<EQ::Net::DaybreakConnection> GetRawConnection() const {
return m_connection;
}
virtual Stats GetStats() const; virtual Stats GetStats() const;
virtual void ResetStats();
virtual EQStreamManagerInterface* GetManager() const;
private: private:
EQStreamManager *m_owner; EQStreamManagerInterface *m_owner;
std::shared_ptr<DaybreakConnection> m_connection; std::shared_ptr<DaybreakConnection> m_connection;
OpcodeManager **m_opcode_manager; OpcodeManager **m_opcode_manager;
std::deque<std::unique_ptr<EQ::Net::Packet>> m_packet_queue; std::deque<std::unique_ptr<EQ::Net::Packet>> m_packet_queue;

View File

@ -286,35 +286,11 @@ RULE_INT(Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before se
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Pathing) RULE_CATEGORY(Pathing)
// Some of these rules may benefit by being made into columns in the zone table,
// for instance, in dungeons, the min LOS distances could be substantially lowered.
RULE_BOOL(Pathing, Aggro, true) // Enable pathing for aggroed mobs.
RULE_BOOL(Pathing, AggroReturnToGrid, true) // Enable pathing for aggroed roaming mobs returning to their previous waypoint.
RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point. RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point.
RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client. RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client.
RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear
RULE_REAL(Pathing, ZDiffThresholdNew, 80) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. RULE_REAL(Pathing, NavmeshStepSize, 100.0f)
RULE_INT(Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f)
RULE_INT(Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved.
RULE_INT(Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved.
// When a path has a path node route and it's target changes position, if it has RouteUpdateFrequencyNodeCount or less nodes to go on it's
// current path, it will recalculate it's path based on the RouteUpdateFrequencyShort timer, otherwise it will use the
// RouteUpdateFrequencyLong timer.
RULE_INT(Pathing, RouteUpdateFrequencyNodeCount, 5)
RULE_REAL(Pathing, MinDistanceForLOSCheckShort, 40000) // (NoRoot). While following a path, only check for LOS to target within this distance.
RULE_REAL(Pathing, MinDistanceForLOSCheckLong, 1000000) // (NoRoot). Min distance when initially attempting to acquire the target.
RULE_INT(Pathing, MinNodesLeftForLOSCheck, 4) // Only check for LOS when we are down to this many path nodes left to run.
// This next rule was put in for situations where the mob and it's target may be on different sides of a 'hazard', e.g. a pit
// If the mob has LOS to it's target, even though there is a hazard in it's way, it may break off from the node path and run at
// the target, only to later detect the hazard and re-acquire a node path. Depending upon the placement of the path nodes, this
// can lead to the mob looping. The rule is intended to allow the mob to at least get closer to it's target each time before
// checking LOS and trying to head straight for it.
RULE_INT(Pathing, MinNodesTraversedForLOSCheck, 3) // Only check for LOS after we have traversed this many path nodes.
RULE_INT(Pathing, CullNodesFromStart, 1) // Checks LOS from Start point to second node for this many nodes and removes first node if there is LOS
RULE_INT(Pathing, CullNodesFromEnd, 1) // Checks LOS from End point to second to last node for this many nodes and removes last node if there is LOS
RULE_REAL(Pathing, CandidateNodeRangeXY, 400) // When searching for path start/end nodes, only nodes within this range will be considered.
RULE_REAL(Pathing, CandidateNodeRangeZ, 10) // When searching for path start/end nodes, only nodes within this range will be considered.
RULE_REAL(Pathing, NavmeshStepSize, 30.0f)
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Watermap) RULE_CATEGORY(Watermap)
@ -710,6 +686,7 @@ RULE_REAL(Network, ResendDelayFactor, 1.5)
RULE_INT(Network, ResendDelayMinMS, 100) RULE_INT(Network, ResendDelayMinMS, 100)
RULE_INT(Network, ResendDelayMaxMS, 5000) RULE_INT(Network, ResendDelayMaxMS, 5000)
RULE_REAL(Network, ClientDataRate, 0.0) // KB / sec, 0.0 disabled RULE_REAL(Network, ClientDataRate, 0.0) // KB / sec, 0.0 disabled
RULE_BOOL(Network, TrackOpcodeStats, false)
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(QueryServ) RULE_CATEGORY(QueryServ)

View File

@ -27,7 +27,7 @@ extern bool run_server;
ClientManager::ClientManager() ClientManager::ClientManager()
{ {
int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str()); int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str());
EQ::Net::EQStreamManagerOptions titanium_opts(titanium_port, false, false); EQStreamManagerInterfaceOptions titanium_opts(titanium_port, false, false);
titanium_stream = new EQ::Net::EQStreamManager(titanium_opts); titanium_stream = new EQ::Net::EQStreamManager(titanium_opts);
titanium_ops = new RegularOpcodeManager; titanium_ops = new RegularOpcodeManager;
if (!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str())) if (!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str()))
@ -38,14 +38,14 @@ ClientManager::ClientManager()
} }
titanium_stream->OnNewConnection([this](std::shared_ptr<EQ::Net::EQStream> stream) { titanium_stream->OnNewConnection([this](std::shared_ptr<EQ::Net::EQStream> stream) {
LogF(Logs::General, Logs::Login_Server, "New Titanium client connection from {0}:{1}", stream->GetRawConnection()->RemoteEndpoint(), stream->GetRemotePort()); LogF(Logs::General, Logs::Login_Server, "New Titanium client connection from {0}:{1}", stream->GetRemoteIP(), stream->GetRemotePort());
stream->SetOpcodeManager(&titanium_ops); stream->SetOpcodeManager(&titanium_ops);
Client *c = new Client(stream, cv_titanium); Client *c = new Client(stream, cv_titanium);
clients.push_back(c); clients.push_back(c);
}); });
int sod_port = atoi(server.config->GetVariable("SoD", "port").c_str()); int sod_port = atoi(server.config->GetVariable("SoD", "port").c_str());
EQ::Net::EQStreamManagerOptions sod_opts(sod_port, false, false); EQStreamManagerInterfaceOptions sod_opts(sod_port, false, false);
sod_stream = new EQ::Net::EQStreamManager(sod_opts); sod_stream = new EQ::Net::EQStreamManager(sod_opts);
sod_ops = new RegularOpcodeManager; sod_ops = new RegularOpcodeManager;
if (!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str())) if (!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str()))
@ -56,7 +56,7 @@ ClientManager::ClientManager()
} }
sod_stream->OnNewConnection([this](std::shared_ptr<EQ::Net::EQStream> stream) { sod_stream->OnNewConnection([this](std::shared_ptr<EQ::Net::EQStream> stream) {
LogF(Logs::General, Logs::Login_Server, "New SoD client connection from {0}:{1}", stream->GetRawConnection()->RemoteEndpoint(), stream->GetRemotePort()); LogF(Logs::General, Logs::Login_Server, "New SoD client connection from {0}:{1}", stream->GetRemoteIP(), stream->GetRemotePort());
stream->SetOpcodeManager(&sod_ops); stream->SetOpcodeManager(&sod_ops);
Client *c = new Client(stream, cv_sod); Client *c = new Client(stream, cv_sod);
clients.push_back(c); clients.push_back(c);

View File

@ -467,7 +467,7 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) {
} }
Clientlist::Clientlist(int ChatPort) { Clientlist::Clientlist(int ChatPort) {
EQ::Net::EQStreamManagerOptions chat_opts(ChatPort, false, false); EQStreamManagerInterfaceOptions chat_opts(ChatPort, false, false);
chat_opts.opcode_size = 1; chat_opts.opcode_size = 1;
chat_opts.daybreak_options.stale_connection_ms = 300000; chat_opts.daybreak_options.stale_connection_ms = 300000;
chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
@ -483,7 +483,7 @@ Clientlist::Clientlist(int ChatPort) {
exit(1); exit(1);
chatsf->OnNewConnection([this](std::shared_ptr<EQ::Net::EQStream> stream) { chatsf->OnNewConnection([this](std::shared_ptr<EQ::Net::EQStream> stream) {
LogF(Logs::General, Logs::Login_Server, "New Client UDP connection from {0}:{1}", stream->GetRawConnection()->RemoteEndpoint(), stream->GetRemotePort()); LogF(Logs::General, Logs::Login_Server, "New Client UDP connection from {0}:{1}", stream->GetRemoteIP(), stream->GetRemotePort());
stream->SetOpcodeManager(&ChatOpMgr); stream->SetOpcodeManager(&ChatOpMgr);
auto c = new Client(stream); auto c = new Client(stream);

View File

@ -498,7 +498,7 @@ int main(int argc, char** argv) {
web_interface.RemoveConnection(connection); web_interface.RemoveConnection(connection);
}); });
EQ::Net::EQStreamManagerOptions opts(9000, false, false); EQStreamManagerInterfaceOptions opts(9000, false, false);
opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
@ -522,7 +522,7 @@ int main(int argc, char** argv) {
eqsm.OnNewConnection([&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) { eqsm.OnNewConnection([&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) {
stream_identifier.AddStream(stream); stream_identifier.AddStream(stream);
LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->GetRawConnection()->RemoteEndpoint(), ntohs(stream->GetRemotePort())); LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->GetRemoteIP(), ntohs(stream->GetRemotePort()));
}); });
while (RunLoops) { while (RunLoops) {

View File

@ -9487,8 +9487,15 @@ void command_netstats(Client *c, const Seperator *sep)
client = c->GetTarget()->CastToClient(); client = c->GetTarget()->CastToClient();
} }
if (strcasecmp(sep->arg[1], "reset") == 0) {
auto connection = c->Connection();
c->Message(0, "Resetting client stats (packet loss will not read correctly after reset).");
connection->ResetStats();
return;
}
auto connection = c->Connection(); auto connection = c->Connection();
auto &opts = connection->GetRawConnection()->GetManager()->GetOptions(); auto &opts = connection->GetManager()->GetOptions();
auto eqs_stats = connection->GetStats(); auto eqs_stats = connection->GetStats();
auto &stats = eqs_stats.DaybreakStats; auto &stats = eqs_stats.DaybreakStats;
auto now = EQ::Net::Clock::now(); auto now = EQ::Net::Clock::now();
@ -9517,25 +9524,27 @@ void command_netstats(Client *c, const Seperator *sep)
c->Message(0, "Resent Non-Fragments: %u (%.2f/sec)", stats.resent_full, stats.resent_full / sec_since_stats_reset); c->Message(0, "Resent Non-Fragments: %u (%.2f/sec)", stats.resent_full, stats.resent_full / sec_since_stats_reset);
c->Message(0, "Dropped Datarate Packets: %u (%.2f/sec)", stats.dropped_datarate_packets, stats.dropped_datarate_packets / sec_since_stats_reset); c->Message(0, "Dropped Datarate Packets: %u (%.2f/sec)", stats.dropped_datarate_packets, stats.dropped_datarate_packets / sec_since_stats_reset);
if (opts.outgoing_data_rate > 0.0) { if (opts.daybreak_options.outgoing_data_rate > 0.0) {
c->Message(0, "Outgoing Link Saturation %.2f%% (%.2fkb/sec)", 100.0 * (1.0 - ((opts.outgoing_data_rate - stats.datarate_remaining) / opts.outgoing_data_rate)), opts.outgoing_data_rate); c->Message(0, "Outgoing Link Saturation %.2f%% (%.2fkb/sec)", 100.0 * (1.0 - ((opts.daybreak_options.outgoing_data_rate - stats.datarate_remaining) / opts.daybreak_options.outgoing_data_rate)), opts.daybreak_options.outgoing_data_rate);
} }
c->Message(0, "--------------------------------------------------------------------"); if (opts.track_opcode_stats) {
c->Message(0, "Sent Packet Types"); c->Message(0, "--------------------------------------------------------------------");
for (auto i = 0; i < _maxEmuOpcode; ++i) { c->Message(0, "Sent Packet Types");
auto cnt = eqs_stats.SentCount[i]; for (auto i = 0; i < _maxEmuOpcode; ++i) {
if (cnt > 0) { auto cnt = eqs_stats.SentCount[i];
c->Message(0, "%s: %u", OpcodeNames[i], cnt); if (cnt > 0) {
c->Message(0, "%s: %u (%.2f / sec)", OpcodeNames[i], cnt, cnt / sec_since_stats_reset);
}
} }
}
c->Message(0, "--------------------------------------------------------------------"); c->Message(0, "--------------------------------------------------------------------");
c->Message(0, "Recv Packet Types"); c->Message(0, "Recv Packet Types");
for (auto i = 0; i < _maxEmuOpcode; ++i) { for (auto i = 0; i < _maxEmuOpcode; ++i) {
auto cnt = eqs_stats.RecvCount[i]; auto cnt = eqs_stats.RecvCount[i];
if (cnt > 0) { if (cnt > 0) {
c->Message(0, "%s: %u", OpcodeNames[i], cnt); c->Message(0, "%s: %u (%.2f / sec)", OpcodeNames[i], cnt, cnt / sec_since_stats_reset);
}
} }
} }
@ -12208,33 +12217,32 @@ void command_network(Client *c, const Seperator *sep)
if (!strcasecmp(sep->arg[1], "getopt")) if (!strcasecmp(sep->arg[1], "getopt"))
{ {
auto eqsi = c->Connection(); auto eqsi = c->Connection();
auto dbc = eqsi->GetRawConnection(); auto manager = eqsi->GetManager();
auto manager = dbc->GetManager();
auto &opts = manager->GetOptions(); auto &opts = manager->GetOptions();
if (!strcasecmp(sep->arg[2], "all")) if (!strcasecmp(sep->arg[2], "all"))
{ {
c->Message(0, "max_packet_size: %llu", opts.max_packet_size); c->Message(0, "max_packet_size: %llu", opts.daybreak_options.max_packet_size);
c->Message(0, "max_connection_count: %llu", opts.max_connection_count); c->Message(0, "max_connection_count: %llu", opts.daybreak_options.max_connection_count);
c->Message(0, "keepalive_delay_ms: %llu", opts.keepalive_delay_ms); c->Message(0, "keepalive_delay_ms: %llu", opts.daybreak_options.keepalive_delay_ms);
c->Message(0, "resend_delay_factor: %.2f", opts.resend_delay_factor); c->Message(0, "resend_delay_factor: %.2f", opts.daybreak_options.resend_delay_factor);
c->Message(0, "resend_delay_ms: %llu", opts.resend_delay_ms); c->Message(0, "resend_delay_ms: %llu", opts.daybreak_options.resend_delay_ms);
c->Message(0, "resend_delay_min: %llu", opts.resend_delay_min); c->Message(0, "resend_delay_min: %llu", opts.daybreak_options.resend_delay_min);
c->Message(0, "resend_delay_max: %llu", opts.resend_delay_max); c->Message(0, "resend_delay_max: %llu", opts.daybreak_options.resend_delay_max);
c->Message(0, "connect_delay_ms: %llu", opts.connect_delay_ms); c->Message(0, "connect_delay_ms: %llu", opts.daybreak_options.connect_delay_ms);
c->Message(0, "connect_stale_ms: %llu", opts.connect_stale_ms); c->Message(0, "connect_stale_ms: %llu", opts.daybreak_options.connect_stale_ms);
c->Message(0, "stale_connection_ms: %llu", opts.stale_connection_ms); c->Message(0, "stale_connection_ms: %llu", opts.daybreak_options.stale_connection_ms);
c->Message(0, "crc_length: %llu", opts.crc_length); c->Message(0, "crc_length: %llu", opts.daybreak_options.crc_length);
c->Message(0, "hold_size: %llu", opts.hold_size); c->Message(0, "hold_size: %llu", opts.daybreak_options.hold_size);
c->Message(0, "hold_length_ms: %llu", opts.hold_length_ms); c->Message(0, "hold_length_ms: %llu", opts.daybreak_options.hold_length_ms);
c->Message(0, "simulated_in_packet_loss: %llu", opts.simulated_in_packet_loss); c->Message(0, "simulated_in_packet_loss: %llu", opts.daybreak_options.simulated_in_packet_loss);
c->Message(0, "simulated_out_packet_loss: %llu", opts.simulated_out_packet_loss); c->Message(0, "simulated_out_packet_loss: %llu", opts.daybreak_options.simulated_out_packet_loss);
c->Message(0, "tic_rate_hertz: %.2f", opts.tic_rate_hertz); c->Message(0, "tic_rate_hertz: %.2f", opts.daybreak_options.tic_rate_hertz);
c->Message(0, "resend_timeout: %llu", opts.resend_timeout); c->Message(0, "resend_timeout: %llu", opts.daybreak_options.resend_timeout);
c->Message(0, "connection_close_time: %llu", opts.connection_close_time); c->Message(0, "connection_close_time: %llu", opts.daybreak_options.connection_close_time);
c->Message(0, "encode_passes[0]: %llu", opts.encode_passes[0]); c->Message(0, "encode_passes[0]: %llu", opts.daybreak_options.encode_passes[0]);
c->Message(0, "encode_passes[1]: %llu", opts.encode_passes[1]); c->Message(0, "encode_passes[1]: %llu", opts.daybreak_options.encode_passes[1]);
c->Message(0, "port: %llu", opts.port); c->Message(0, "port: %llu", opts.daybreak_options.port);
} }
else { else {
c->Message(0, "Unknown get option: %s", sep->arg[2]); c->Message(0, "Unknown get option: %s", sep->arg[2]);
@ -12267,9 +12275,8 @@ void command_network(Client *c, const Seperator *sep)
else if (!strcasecmp(sep->arg[1], "setopt")) else if (!strcasecmp(sep->arg[1], "setopt"))
{ {
auto eqsi = c->Connection(); auto eqsi = c->Connection();
auto dbc = eqsi->GetRawConnection(); auto manager = eqsi->GetManager();
auto manager = dbc->GetManager(); auto &opts = manager->MutateOptions();
auto &opts = manager->GetOptions();
if (!strcasecmp(sep->arg[3], "")) if (!strcasecmp(sep->arg[3], ""))
{ {
@ -12280,63 +12287,63 @@ void command_network(Client *c, const Seperator *sep)
std::string value = sep->arg[3]; std::string value = sep->arg[3];
if (!strcasecmp(sep->arg[2], "max_connection_count")) if (!strcasecmp(sep->arg[2], "max_connection_count"))
{ {
opts.max_connection_count = std::stoull(value); opts.daybreak_options.max_connection_count = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "keepalive_delay_ms")) else if (!strcasecmp(sep->arg[2], "keepalive_delay_ms"))
{ {
opts.keepalive_delay_ms = std::stoull(value); opts.daybreak_options.keepalive_delay_ms = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "resend_delay_factor")) else if (!strcasecmp(sep->arg[2], "resend_delay_factor"))
{ {
opts.resend_delay_factor = std::stod(value); opts.daybreak_options.resend_delay_factor = std::stod(value);
} }
else if (!strcasecmp(sep->arg[2], "resend_delay_ms")) else if (!strcasecmp(sep->arg[2], "resend_delay_ms"))
{ {
opts.resend_delay_ms = std::stoull(value); opts.daybreak_options.resend_delay_ms = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "resend_delay_min")) else if (!strcasecmp(sep->arg[2], "resend_delay_min"))
{ {
opts.resend_delay_min = std::stoull(value); opts.daybreak_options.resend_delay_min = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "resend_delay_max")) else if (!strcasecmp(sep->arg[2], "resend_delay_max"))
{ {
opts.resend_delay_max = std::stoull(value); opts.daybreak_options.resend_delay_max = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "connect_delay_ms")) else if (!strcasecmp(sep->arg[2], "connect_delay_ms"))
{ {
opts.connect_delay_ms = std::stoull(value); opts.daybreak_options.connect_delay_ms = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "connect_stale_ms")) else if (!strcasecmp(sep->arg[2], "connect_stale_ms"))
{ {
opts.connect_stale_ms = std::stoull(value); opts.daybreak_options.connect_stale_ms = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "stale_connection_ms")) else if (!strcasecmp(sep->arg[2], "stale_connection_ms"))
{ {
opts.stale_connection_ms = std::stoull(value); opts.daybreak_options.stale_connection_ms = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "hold_size")) else if (!strcasecmp(sep->arg[2], "hold_size"))
{ {
opts.hold_size = std::stoull(value); opts.daybreak_options.hold_size = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "hold_length_ms")) else if (!strcasecmp(sep->arg[2], "hold_length_ms"))
{ {
opts.hold_length_ms = std::stoull(value); opts.daybreak_options.hold_length_ms = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "simulated_in_packet_loss")) else if (!strcasecmp(sep->arg[2], "simulated_in_packet_loss"))
{ {
opts.simulated_in_packet_loss = std::stoull(value); opts.daybreak_options.simulated_in_packet_loss = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "simulated_out_packet_loss")) else if (!strcasecmp(sep->arg[2], "simulated_out_packet_loss"))
{ {
opts.simulated_out_packet_loss = std::stoull(value); opts.daybreak_options.simulated_out_packet_loss = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "resend_timeout")) else if (!strcasecmp(sep->arg[2], "resend_timeout"))
{ {
opts.resend_timeout = std::stoull(value); opts.daybreak_options.resend_timeout = std::stoull(value);
} }
else if (!strcasecmp(sep->arg[2], "connection_close_time")) else if (!strcasecmp(sep->arg[2], "connection_close_time"))
{ {
opts.connection_close_time = std::stoull(value); opts.daybreak_options.connection_close_time = std::stoull(value);
} }
else { else {
c->Message(0, "Unknown set option: %s", sep->arg[2]); c->Message(0, "Unknown set option: %s", sep->arg[2]);

View File

@ -671,24 +671,27 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float
} }
} }
else { else {
float short_range = RuleR(Pathing, ShortMovementUpdateRange);
float long_range = zone->GetMaxMovementUpdateRange();
for (auto &c : _impl->Clients) { for (auto &c : _impl->Clients) {
float dist = c->CalculateDistance(m->GetX(), m->GetY(), m->GetZ()); float dist = c->CalculateDistance(m->GetX(), m->GetY(), m->GetZ());
bool match = false; bool match = false;
if (range & ClientRangeClose) { if (range & ClientRangeClose) {
if (dist < 250.0f) { if (dist < short_range) {
match = true; match = true;
} }
} }
if (!match && range & ClientRangeMedium) { if (!match && range & ClientRangeMedium) {
if (dist >= 250.0f && dist < 1500.0f) { if (dist >= short_range && dist < long_range) {
match = true; match = true;
} }
} }
if (!match && range & ClientRangeLong) { if (!match && range & ClientRangeLong) {
if (dist >= 1500.0f) { if (dist >= long_range) {
match = true; match = true;
} }
} }

View File

@ -500,18 +500,19 @@ int main(int argc, char** argv) {
if (!eqsf_open && Config->ZonePort != 0) { if (!eqsf_open && Config->ZonePort != 0) {
Log(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort); Log(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort);
EQ::Net::EQStreamManagerOptions opts(Config->ZonePort, false, true); EQStreamManagerInterfaceOptions opts(Config->ZonePort, false, true);
opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS);
opts.daybreak_options.outgoing_data_rate = RuleR(Network, ClientDataRate); opts.daybreak_options.outgoing_data_rate = RuleR(Network, ClientDataRate);
opts.track_opcode_stats = RuleB(Network, TrackOpcodeStats);
eqsm.reset(new EQ::Net::EQStreamManager(opts)); eqsm.reset(new EQ::Net::EQStreamManager(opts));
eqsf_open = true; eqsf_open = true;
eqsm->OnNewConnection([&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) { eqsm->OnNewConnection([&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) {
stream_identifier.AddStream(stream); stream_identifier.AddStream(stream);
LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->GetRawConnection()->RemoteEndpoint(), ntohs(stream->GetRemotePort())); LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->GetRemoteIP(), ntohs(stream->GetRemotePort()));
}); });
} }

View File

@ -41,7 +41,7 @@ glm::mat4 CreateScaleMatrix(float sx, float sy, float sz) {
return scale; return scale;
} }
OrientedBoundingBox::OrientedBoundingBox(glm::vec3 pos, glm::vec3 rot, glm::vec3 scale, glm::vec3 extents) { OrientedBoundingBox::OrientedBoundingBox(const glm::vec3 &pos, const glm::vec3 &rot, const glm::vec3 &scale, const glm::vec3 &extents) {
min_x = -extents.x; min_x = -extents.x;
max_x = extents.x; max_x = extents.x;
@ -81,7 +81,7 @@ OrientedBoundingBox::OrientedBoundingBox(glm::vec3 pos, glm::vec3 rot, glm::vec3
inverted_transformation = glm::inverse(transformation); inverted_transformation = glm::inverse(transformation);
} }
bool OrientedBoundingBox::ContainsPoint(glm::vec3 p) const { bool OrientedBoundingBox::ContainsPoint(const glm::vec3 &p) const {
glm::vec4 pt(p.x, p.y, p.z, 1); glm::vec4 pt(p.x, p.y, p.z, 1);
glm::vec4 box_space_p = inverted_transformation * pt; glm::vec4 box_space_p = inverted_transformation * pt;

View File

@ -8,10 +8,10 @@ class OrientedBoundingBox
{ {
public: public:
OrientedBoundingBox() { } OrientedBoundingBox() { }
OrientedBoundingBox(glm::vec3 pos, glm::vec3 rot, glm::vec3 scale, glm::vec3 extents); OrientedBoundingBox(const glm::vec3 &pos, const glm::vec3 &rot, const glm::vec3 &scale, const glm::vec3 &extents);
~OrientedBoundingBox() { } ~OrientedBoundingBox() { }
bool ContainsPoint(glm::vec3 p) const; bool ContainsPoint(const glm::vec3 &p) const;
glm::mat4& GetTransformation() { return transformation; } glm::mat4& GetTransformation() { return transformation; }
glm::mat4& GetInvertedTransformation() { return inverted_transformation; } glm::mat4& GetInvertedTransformation() { return inverted_transformation; }

View File

@ -12,7 +12,7 @@
extern Zone *zone; extern Zone *zone;
const int MaxNavmeshNodes = 4096; const int MaxNavmeshNodes = 1024;
struct PathfinderNavmesh::Implementation struct PathfinderNavmesh::Implementation
{ {

View File

@ -30,7 +30,8 @@ bool WaterMapV2::InLava(const glm::vec3& location) const {
} }
bool WaterMapV2::InLiquid(const glm::vec3& location) const { bool WaterMapV2::InLiquid(const glm::vec3& location) const {
return InWater(location) || InLava(location) || InVWater(location); auto rt = ReturnRegionType(location);
return rt == RegionTypeWater || rt == RegionTypeVWater || rt == RegionTypeLava;
} }
bool WaterMapV2::InPvP(const glm::vec3& location) const { bool WaterMapV2::InPvP(const glm::vec3& location) const {

View File

@ -1070,14 +1070,14 @@ bool Zone::LoadZoneCFG(const char* filename, uint16 instance_id)
map_name = nullptr; map_name = nullptr;
if(!database.GetZoneCFG(database.GetZoneID(filename), instance_id, &newzone_data, can_bind, if(!database.GetZoneCFG(database.GetZoneID(filename), instance_id, &newzone_data, can_bind,
can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name)) can_combat, can_levitate, can_castoutdoor, is_city, is_hotzone, allow_mercs, max_movement_update_range, zone_type, default_ruleset, &map_name))
{ {
// If loading a non-zero instance failed, try loading the default // If loading a non-zero instance failed, try loading the default
if (instance_id != 0) if (instance_id != 0)
{ {
safe_delete_array(map_name); safe_delete_array(map_name);
if(!database.GetZoneCFG(database.GetZoneID(filename), 0, &newzone_data, can_bind, can_combat, can_levitate, if(!database.GetZoneCFG(database.GetZoneID(filename), 0, &newzone_data, can_bind, can_combat, can_levitate,
can_castoutdoor, is_city, is_hotzone, allow_mercs, zone_type, default_ruleset, &map_name)) can_castoutdoor, is_city, is_hotzone, allow_mercs, max_movement_update_range, zone_type, default_ruleset, &map_name))
{ {
Log(Logs::General, Logs::Error, "Error loading the Zone Config."); Log(Logs::General, Logs::Error, "Error loading the Zone Config.");
return false; return false;

View File

@ -313,6 +313,8 @@ public:
} }
} }
double GetMaxMovementUpdateRange() const { return max_movement_update_range; }
/** /**
* Modding hooks * Modding hooks
*/ */
@ -332,6 +334,7 @@ private:
bool m_ucss_available; bool m_ucss_available;
bool staticzone; bool staticzone;
bool zone_has_current_time; bool zone_has_current_time;
double max_movement_update_range;
char *long_name; char *long_name;
char *map_name; char *map_name;
char *short_name; char *short_name;

View File

@ -80,7 +80,21 @@ bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
return true; return true;
} }
bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *zone_data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename) { bool ZoneDatabase::GetZoneCFG(
uint32 zoneid,
uint16 instance_id,
NewZone_Struct *zone_data,
bool &can_bind,
bool &can_combat,
bool &can_levitate,
bool &can_castoutdoor,
bool &is_city,
bool &is_hotzone,
bool &allow_mercs,
double &max_movement_update_range,
uint8 &zone_type,
int &ruleset,
char **map_filename) {
*map_filename = new char[100]; *map_filename = new char[100];
zone_data->zone_id = zoneid; zone_data->zone_id = zoneid;
@ -147,7 +161,8 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
"fast_regen_hp, " // 57 "fast_regen_hp, " // 57
"fast_regen_mana, " // 58 "fast_regen_mana, " // 58
"fast_regen_endurance, " // 59 "fast_regen_endurance, " // 59
"npc_max_aggro_dist " // 60 "npc_max_aggro_dist, " // 60
"max_movement_update_range " // 61
"FROM zone WHERE zoneidnumber = %i AND version = %i", "FROM zone WHERE zoneidnumber = %i AND version = %i",
zoneid, instance_id); zoneid, instance_id);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
@ -206,7 +221,7 @@ bool ZoneDatabase::GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
can_levitate = atoi(row[33]) == 0 ? false : true; can_levitate = atoi(row[33]) == 0 ? false : true;
can_castoutdoor = atoi(row[34]) == 0 ? false : true; can_castoutdoor = atoi(row[34]) == 0 ? false : true;
is_hotzone = atoi(row[35]) == 0 ? false : true; is_hotzone = atoi(row[35]) == 0 ? false : true;
max_movement_update_range = atof(row[61]);
ruleset = atoi(row[36]); ruleset = atoi(row[36]);
zone_data->SuspendBuffs = atoi(row[37]); zone_data->SuspendBuffs = atoi(row[37]);

View File

@ -382,7 +382,21 @@ public:
bool LoadAlternateAdvancement(Client *c); bool LoadAlternateAdvancement(Client *c);
/* Zone related */ /* Zone related */
bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename); bool GetZoneCFG(
uint32 zoneid,
uint16 instance_id,
NewZone_Struct *data,
bool &can_bind,
bool &can_combat,
bool &can_levitate,
bool &can_castoutdoor,
bool &is_city,
bool &is_hotzone,
bool &allow_mercs,
double &max_movement_update_range,
uint8 &zone_type,
int &ruleset,
char **map_filename);
bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd); bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd);
bool LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list,const char* zonename, uint32 version); bool LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list,const char* zonename, uint32 version);
bool UpdateZoneSafeCoords(const char* zonename, const glm::vec3& location); bool UpdateZoneSafeCoords(const char* zonename, const glm::vec3& location);