Retransmit support added back in (stupid compile flags), prelim work on lua_client stuff, took out a few redundant or non-working functions

This commit is contained in:
KimLS 2013-05-25 01:08:30 -07:00
parent d25d8187b6
commit 79a9d2112a
17 changed files with 405 additions and 491 deletions

View File

@ -23,6 +23,7 @@
#include "Mutex.h" #include "Mutex.h"
#include "op_codes.h" #include "op_codes.h"
#include "CRC16.h" #include "CRC16.h"
#include "platform.h"
#include <string> #include <string>
#include <iomanip> #include <iomanip>
@ -30,13 +31,6 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#if defined(ZONE) || defined(WORLD)
#define RETRANSMITS
#endif
#ifdef RETRANSMITS
#include "rulesys.h"
#endif
#ifdef _WINDOWS #ifdef _WINDOWS
#include <time.h> #include <time.h>
#else #else
@ -75,17 +69,20 @@ void EQStream::init() {
BytesWritten=0; BytesWritten=0;
SequencedBase = 0; SequencedBase = 0;
NextSequencedSend = 0; NextSequencedSend = 0;
#ifdef RETRANSMITS
retransmittimer = Timer::GetCurrentTime(); if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
retransmittimeout = 500 * RuleR(EQStream, RetransmitTimeoutMult); //use 500ms as base before we have connection stats retransmittimer = Timer::GetCurrentTime();
#endif retransmittimeout = 500 * RETRANSMIT_TIMEOUT_MULT;
}
OpMgr = nullptr; OpMgr = nullptr;
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
_log(NET__ERROR, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); _log(NET__ERROR, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
if(NextSequencedSend > SequencedQueue.size()) {
_log(NET__ERROR, _L "init Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); if(NextSequencedSend > SequencedQueue.size()) {
} _log(NET__ERROR, _L "init Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
}
} }
EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
@ -118,7 +115,7 @@ EQProtocolPacket *EQStream::MakeProtocolPacket(const unsigned char *buf, uint32
void EQStream::ProcessPacket(EQProtocolPacket *p) void EQStream::ProcessPacket(EQProtocolPacket *p)
{ {
uint32 processed=0,subpacket_length=0; uint32 processed=0, subpacket_length=0;
if (p == nullptr) if (p == nullptr)
return; return;
// Raw Application packet // Raw Application packet
@ -304,9 +301,10 @@ uint32 processed=0,subpacket_length=0;
#ifndef COLLECTOR #ifndef COLLECTOR
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
AckPackets(seq); AckPackets(seq);
#ifdef RETRANSMITS
retransmittimer = Timer::GetCurrentTime(); if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
#endif retransmittimer = Timer::GetCurrentTime();
}
#endif #endif
} }
break; break;
@ -409,19 +407,24 @@ uint32 processed=0,subpacket_length=0;
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
MOutboundQueue.lock(); MOutboundQueue.lock();
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
_log(NET__ERROR, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); _log(NET__ERROR, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
if(NextSequencedSend > SequencedQueue.size()) {
_log(NET__ERROR, _L "Pre-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); if(NextSequencedSend > SequencedQueue.size()) {
} _log(NET__ERROR, _L "Pre-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
}
//if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid.
if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) { if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) {
_log(NET__NET_TRACE, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, _log(NET__NET_TRACE, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L,
seq, SequencedBase, SequencedBase+NextSequencedSend); seq, SequencedBase, SequencedBase+NextSequencedSend);
#ifdef RETRANSMITS
if (!RuleB(EQStream, RetransmitAckedPackets)) { bool retransmit_acked_packets = false;
#endif if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
retransmit_acked_packets = RETRANSMIT_ACKED_PACKETS;
}
if(!retransmit_acked_packets) {
uint16 sqsize = SequencedQueue.size(); uint16 sqsize = SequencedQueue.size();
uint16 index = seq - SequencedBase; uint16 index = seq - SequencedBase;
_log(NET__NET_TRACE, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize); _log(NET__NET_TRACE, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize);
@ -431,22 +434,24 @@ if(NextSequencedSend > SequencedQueue.size()) {
sitr += index; sitr += index;
(*sitr)->acked = true; (*sitr)->acked = true;
} }
#ifdef RETRANSMITS
} }
if (RuleR(EQStream, RetransmitTimeoutMult)) { // only choose new behavior if multiplier is set
if(RETRANSMIT_TIMEOUT_MULT) {
retransmittimer = Timer::GetCurrentTime(); retransmittimer = Timer::GetCurrentTime();
} }
#endif
NextSequencedSend = 0; NextSequencedSend = 0;
} else { } else {
_log(NET__NET_TRACE, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq); _log(NET__NET_TRACE, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq);
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
_log(NET__ERROR, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
} _log(NET__ERROR, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
if(NextSequencedSend > SequencedQueue.size()) { }
_log(NET__ERROR, _L "Post-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
} if(NextSequencedSend > SequencedQueue.size()) {
_log(NET__ERROR, _L "Post-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
}
MOutboundQueue.unlock(); MOutboundQueue.unlock();
#endif #endif
} }
@ -468,19 +473,21 @@ if(NextSequencedSend > SequencedQueue.size()) {
Stats->packets_sent=x; Stats->packets_sent=x;
NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse,p->pBuffer,p->size)); NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse,p->pBuffer,p->size));
AdjustRates(ntohl(Stats->average_delta)); AdjustRates(ntohl(Stats->average_delta));
#ifdef RETRANSMITS
if (RuleR(EQStream, RetransmitTimeoutMult) && ntohl(Stats->average_delta)) { if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
//recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value if(RETRANSMIT_TIMEOUT_MULT && ntohl(Stats->average_delta)) {
if((ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) > (ntohl(Stats->average_delta) * 2)) { //recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value
retransmittimeout = (ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) * RuleR(EQStream, RetransmitTimeoutMult); if((ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta)) > (ntohl(Stats->average_delta) * 2)) {
} else { retransmittimeout = (ntohl(Stats->last_local_delta) + ntohl(Stats->last_remote_delta))
retransmittimeout = ntohl(Stats->average_delta) * 2 * RuleR(EQStream, RetransmitTimeoutMult); * RETRANSMIT_TIMEOUT_MULT;
} else {
retransmittimeout = ntohl(Stats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT;
}
if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
retransmittimeout = RETRANSMIT_TIMEOUT_MAX;
_log(NET__NET_TRACE, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout);
} }
if(retransmittimeout > RuleI(EQStream, RetransmitTimeoutMax))
retransmittimeout = RuleI(EQStream, RetransmitTimeoutMax);
_log(NET__NET_TRACE, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout);
} }
#endif
#endif #endif
} }
break; break;
@ -527,16 +534,6 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
uint16 opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode); uint16 opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode);
//make sure this packet is compatible with this stream
/* if(StreamType == UnknownStream || StreamType == ChatOrMailStream) {
_log(NET__DEBUG, _L "Stream type undetermined (%s), packet ignored" __L, StreamTypeString(StreamType));
return;
}
if(pack->GetPacketType() != StreamType) {
_log(NET__ERROR, _L "Trying to queue a packet of type %s into a stream of type %s, dropping it." __L, StreamTypeString(pack->GetPacketType()), StreamTypeString(StreamType));
return;
}*/
_log(NET__APP_TRACE, "Queueing %sacked packet with opcode 0x%x (%s) and length %d", ack_req?"":"non-", opcode, OpcodeManager::EmuToName(pack->emu_opcode), pack->size); _log(NET__APP_TRACE, "Queueing %sacked packet with opcode 0x%x (%s) and length %d", ack_req?"":"non-", opcode, OpcodeManager::EmuToName(pack->emu_opcode), pack->size);
if (!ack_req) { if (!ack_req) {
@ -549,8 +546,8 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
{ {
uint32 chunksize,used; uint32 chunksize,used;
uint32 length; uint32 length;
// Convert the EQApplicationPacket to 1 or more EQProtocolPackets // Convert the EQApplicationPacket to 1 or more EQProtocolPackets
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2)
@ -648,9 +645,9 @@ uint16 Seq=htons(seq);
void EQStream::Write(int eq_fd) void EQStream::Write(int eq_fd)
{ {
std::queue<EQProtocolPacket *> ReadyToSend; std::queue<EQProtocolPacket *> ReadyToSend;
bool SeqEmpty=false,NonSeqEmpty=false; bool SeqEmpty=false, NonSeqEmpty=false;
std::deque<EQProtocolPacket *>::iterator sitr; std::deque<EQProtocolPacket *>::iterator sitr;
// Check our rate to make sure we can send more // Check our rate to make sure we can send more
MRate.lock(); MRate.lock();
@ -673,14 +670,16 @@ std::deque<EQProtocolPacket *>::iterator sitr;
// Place to hold the base packet t combine into // Place to hold the base packet t combine into
EQProtocolPacket *p=nullptr; EQProtocolPacket *p=nullptr;
#ifdef RETRANSMITS if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
// if we have a timeout defined and we have not received an ack recently enough, retransmit from beginning of queue // if we have a timeout defined and we have not received an ack recently enough, retransmit from beginning of queue
if (RuleR(EQStream, RetransmitTimeoutMult) && !SequencedQueue.empty() && NextSequencedSend && (GetState()==ESTABLISHED) && ((retransmittimer+retransmittimeout) < Timer::GetCurrentTime())) { if (RETRANSMIT_TIMEOUT_MULT && !SequencedQueue.empty() && NextSequencedSend &&
_log(NET__NET_TRACE, _L "Timeout since last ack received, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, SequencedBase, SequencedBase+NextSequencedSend); (GetState()==ESTABLISHED) && ((retransmittimer+retransmittimeout) < Timer::GetCurrentTime())) {
NextSequencedSend = 0; _log(NET__NET_TRACE, _L "Timeout since last ack received, starting retransmit at the start of our unacked "
retransmittimer = Timer::GetCurrentTime(); // don't want to endlessly retransmit the first packet "buffer (seq %d, was %d)." __L, SequencedBase, SequencedBase+NextSequencedSend);
NextSequencedSend = 0;
retransmittimer = Timer::GetCurrentTime(); // don't want to endlessly retransmit the first packet
}
} }
#endif
// Find the next sequenced packet to send from the "queue" // Find the next sequenced packet to send from the "queue"
sitr = SequencedQueue.begin(); sitr = SequencedQueue.begin();
@ -723,65 +722,87 @@ std::deque<EQProtocolPacket *>::iterator sitr;
} }
if (sitr!=SequencedQueue.end()) { if (sitr!=SequencedQueue.end()) {
//_log(NET__NET_COMBINE, _L "Send Seq with %d seq packets starting at seq %d, next send %d, and %d non-seq packets." __L, if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
// SequencedQueue.size(), SequencedBase, NextSequencedSend, NonSequencedQueue.size()); _log(NET__ERROR, _L "Pre-Send Seq NSS=%d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, NextSequencedSend, SequencedBase, SequencedQueue.size(), NextOutSeq);
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { }
_log(NET__ERROR, _L "Pre-Send Seq NSS=%d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, NextSequencedSend, SequencedBase, SequencedQueue.size(), NextOutSeq);
}
if(NextSequencedSend > SequencedQueue.size()) {
_log(NET__ERROR, _L "Pre-Send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
}
uint16 seq_send = SequencedBase + NextSequencedSend; //just for logging...
if(SequencedQueue.empty()) {
_log(NET__ERROR, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq);
SeqEmpty=true;
continue;
}
/*if(CompareSequence(NextOutSeq, seq_send) == SeqFuture) {
_log(NET__ERROR, _L "Tried to write a packet beyond the end of the queue! (%d is past next out %d)" __L, seq_send, NextOutSeq);
sitr=SequencedQueue.end();
continue;
}*/
#ifdef RETRANSMITS
if (!RuleB(EQStream, RetransmitAckedPackets) && (*sitr)->acked) {
_log(NET__NET_TRACE, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send);
sitr++;
NextSequencedSend++;
} else if (!p) {
#else
if (!p) {
#endif
// If we don't have a packet to try to combine into, use this one as the base
// Copy it first as it will still live until it is acked
p=(*sitr)->Copy();
_log(NET__NET_COMBINE, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
sitr++;
NextSequencedSend++;
} else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe)
// So just send the base packet (we'll try this packet again later)
_log(NET__NET_COMBINE, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size);
ReadyToSend.push(p);
BytesWritten+=p->size;
p=nullptr;
if (BytesWritten > threshold) { if(NextSequencedSend > SequencedQueue.size()) {
// Sent enough this round, lets stop to be fair _log(NET__ERROR, _L "Pre-Send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
_log(NET__RATES, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold); }
break; uint16 seq_send = SequencedBase + NextSequencedSend; //just for logging...
if(SequencedQueue.empty()) {
_log(NET__ERROR, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq);
SeqEmpty=true;
continue;
}
if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
if (!RETRANSMIT_ACKED_PACKETS && (*sitr)->acked) {
_log(NET__NET_TRACE, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send);
sitr++;
NextSequencedSend++;
} else if (!p) {
// If we don't have a packet to try to combine into, use this one as the base
// Copy it first as it will still live until it is acked
p=(*sitr)->Copy();
_log(NET__NET_COMBINE, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
sitr++;
NextSequencedSend++;
} else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe)
// So just send the base packet (we'll try this packet again later)
_log(NET__NET_COMBINE, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size);
ReadyToSend.push(p);
BytesWritten+=p->size;
p=nullptr;
if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair
_log(NET__RATES, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold);
break;
}
} else {
// Combine worked
_log(NET__NET_COMBINE, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size);
sitr++;
NextSequencedSend++;
} }
} else { } else {
// Combine worked if (!p) {
_log(NET__NET_COMBINE, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); // If we don't have a packet to try to combine into, use this one as the base
sitr++; // Copy it first as it will still live until it is acked
NextSequencedSend++; p=(*sitr)->Copy();
_log(NET__NET_COMBINE, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
sitr++;
NextSequencedSend++;
} else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe)
// So just send the base packet (we'll try this packet again later)
_log(NET__NET_COMBINE, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size);
ReadyToSend.push(p);
BytesWritten+=p->size;
p=nullptr;
if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair
_log(NET__RATES, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold);
break;
}
} else {
// Combine worked
_log(NET__NET_COMBINE, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size);
sitr++;
NextSequencedSend++;
}
}
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
_log(NET__ERROR, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
}
if(NextSequencedSend > SequencedQueue.size()) {
_log(NET__ERROR, _L "Post send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
_log(NET__ERROR, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
}
if(NextSequencedSend > SequencedQueue.size()) {
_log(NET__ERROR, _L "Post send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
}
} else { } else {
// No more sequenced packets // No more sequenced packets
SeqEmpty=true; SeqEmpty=true;
@ -1379,20 +1400,27 @@ void EQStream::Decay()
void EQStream::AdjustRates(uint32 average_delta) void EQStream::AdjustRates(uint32 average_delta)
{ {
#ifdef RETRANSMITS if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
if (average_delta && (average_delta <= RuleI(EQStream, AverageDeltaMax))) { if (average_delta && (average_delta <= AVERAGE_DELTA_MAX)) {
#else MRate.lock();
if (average_delta) { RateThreshold=RATEBASE/average_delta;
#endif DecayRate=DECAYBASE/average_delta;
MRate.lock(); _log(NET__RATES, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
RateThreshold=RATEBASE/average_delta; RateThreshold, DecayRate, average_delta);
DecayRate=DECAYBASE/average_delta; MRate.unlock();
_log(NET__RATES, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); } else {
MRate.unlock(); _log(NET__RATES, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L,
#ifdef RETRANSMITS average_delta, AVERAGE_DELTA_MAX);
}
} else { } else {
_log(NET__RATES, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, average_delta, RuleI(EQStream, AverageDeltaMax)); if (average_delta) {
#endif MRate.lock();
RateThreshold=RATEBASE/average_delta;
DecayRate=DECAYBASE/average_delta;
_log(NET__RATES, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L,
RateThreshold, DecayRate, average_delta);
MRate.unlock();
}
} }
} }

View File

@ -24,6 +24,11 @@
#define RATEBASE 1048576 // 1 MB #define RATEBASE 1048576 // 1 MB
#define DECAYBASE 78642 // RATEBASE/10 #define DECAYBASE 78642 // RATEBASE/10
#define RETRANSMIT_TIMEOUT_MULT 3.0
#define RETRANSMIT_TIMEOUT_MAX 5000
#define AVERAGE_DELTA_MAX 2500
#define RETRANSMIT_ACKED_PACKETS true
#pragma pack(1) #pragma pack(1)
struct SessionRequest { struct SessionRequest {
uint32 UnknownA; uint32 UnknownA;

View File

@ -499,13 +499,6 @@ RULE_CATEGORY( Console )
RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the console session to time out RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the console session to time out
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY( EQStream )
RULE_INT ( EQStream, RetransmitTimeoutMax, 5000 ) // maximum retransmit timeout before retransmitting unacked packets
RULE_INT ( EQStream, AverageDeltaMax, 2500 ) // maximum average rtt where we will still recalculate transmit rates
RULE_REAL ( EQStream, RetransmitTimeoutMult, 3.0 ) // multiplier applied to rtt stats to generate a retransmit timeout value
RULE_BOOL ( EQStream, RetransmitAckedPackets, true ) // should we restransmit packets that were already acked?
RULE_CATEGORY_END()
RULE_CATEGORY( QueryServ ) RULE_CATEGORY( QueryServ )
RULE_BOOL( QueryServ, PlayerChatLogging, false) // Logs Player Chat RULE_BOOL( QueryServ, PlayerChatLogging, false) // Logs Player Chat
RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades

View File

@ -7114,13 +7114,13 @@ const char* Client::GetClassPlural(Client* client) {
void Client::SendWebLink(const char *website) void Client::SendWebLink(const char *website)
{ {
if(website != 0) size_t len = strlen(website) + 1;
if(website != 0 && len > 1)
{ {
std::string str = website; EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + len);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + str.length() + 1);
Weblink_Struct *wl = (Weblink_Struct*)outapp->pBuffer; Weblink_Struct *wl = (Weblink_Struct*)outapp->pBuffer;
memcpy(wl->weblink, str.c_str(), str.length() + 1); memcpy(wl->weblink, website, len);
wl->weblink[str.length() + 1] = '\0'; wl->weblink[len] = '\0';
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
} }

View File

@ -687,7 +687,6 @@ public:
inline uint8 GetBecomeNPCLevel() const { return npclevel; } inline uint8 GetBecomeNPCLevel() const { return npclevel; }
inline void SetBecomeNPC(bool flag) { npcflag = flag; } inline void SetBecomeNPC(bool flag) { npcflag = flag; }
inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; } inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; }
bool LootToStack(uint32 itemid);
void SetFeigned(bool in_feigned); void SetFeigned(bool in_feigned);
/// this cures timing issues cuz dead animation isn't done but server side feigning is? /// this cures timing issues cuz dead animation isn't done but server side feigning is?
inline bool GetFeigned() const { return(feigned); } inline bool GetFeigned() const { return(feigned); }

View File

@ -1914,50 +1914,6 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const
return 0; return 0;
} }
bool Client::LootToStack(uint32 itemid) { //Loots stackable items to existing stacks - Wiz
// @merth: Need to do loot code with new inventory struct
/*
const Item_Struct* item;
int i;
for (i=22; i<=29; i++) {
item = GetItemAt(i);
if (item) {
if (m_pp.invitemproperties[i].charges < 20 && item->ID == itemid)
{
m_pp.invitemproperties[i].charges += 1;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_PlaceItem, sizeof(Item_Struct));
memcpy(outapp->pBuffer, item, outapp->size);
Item_Struct* outitem = (Item_Struct*) outapp->pBuffer;
outitem->equipSlot = i;
outitem->charges = m_pp.invitemproperties[i].charges;
QueuePacket(outapp);
safe_delete(outapp);
return true;
}
}
}
for (i=0; i<=pp_containerinv_size; i++) {
if (m_pp.containerinv[i] != 0xFFFF) {
item = database.GetItem(m_pp.containerinv[i]);
if (m_pp.bagitemproperties[i].charges < 20 && item->ID == itemid)
{
m_pp.bagitemproperties[i].charges += 1;
EQApplicationPacket* outapp = new EQApplicationPacket(OP_PlaceItem, sizeof(Item_Struct));
memcpy(outapp->pBuffer, item, outapp->size);
Item_Struct* outitem = (Item_Struct*) outapp->pBuffer;
outitem->equipSlot = 250+i;
outitem->charges = m_pp.bagitemproperties[i].charges;
QueuePacket(outapp);
safe_delete(outapp);
return true;
}
}
}
*/
return false;
}
// Send an item packet (including all subitems of the item) // Send an item packet (including all subitems of the item)
void Client::SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type) void Client::SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type)
{ {

View File

@ -6,10 +6,25 @@
#include "masterentity.h" #include "masterentity.h"
#include "lua_client.h" #include "lua_client.h"
#include "../common/item.h"
struct InventoryWhere { };
luabind::scope lua_register_client() { luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client") return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>()); .def(luabind::constructor<>());
} }
luabind::scope lua_register_inventory_where() {
return luabind::class_<InventoryWhere>("InventoryWhere")
.enum_("constants")
[
luabind::value("Personal", static_cast<int>(invWherePersonal)),
luabind::value("Bank", static_cast<int>(invWhereBank)),
luabind::value("SharedBank", static_cast<int>(invWhereSharedBank)),
luabind::value("Trading", static_cast<int>(invWhereTrading)),
luabind::value("Cursor", static_cast<int>(invWhereCursor))
];
}
#endif #endif

View File

@ -11,6 +11,7 @@ namespace luabind {
} }
luabind::scope lua_register_client(); luabind::scope lua_register_client();
luabind::scope lua_register_inventory_where();
class Lua_Client : public Lua_Mob class Lua_Client : public Lua_Mob
{ {
@ -39,206 +40,189 @@ public:
void Kick(); void Kick();
void Disconnect(); void Disconnect();
bool IsLD(); bool IsLD();
WorldKick void WorldKick();
GetAnon bool GetAnon();
Duck void Duck();
Stand void Stand();
SetGM void SetGM(bool v);
SetPVP void SetPVP(bool v);
GetPVP bool GetPVP();
GetGM bool GetGM();
SetBaseClass void SetBaseClass(int v);
SetBaseRace void SetBaseRace(int v);
SetBaseGender void SetBaseGender(int v);
GetBaseFace int GetBaseFace();
GetLanguageSkill int GetLanguageSkill();
GetLastName int GetLastName();
GetLDoNPointsTheme int GetLDoNPointsTheme();
GetBaseSTR int GetBaseSTR();
GetBaseSTA int GetBaseSTA();
GetBaseCHA int GetBaseCHA();
GetBaseDEX int GetBaseDEX();
GetBaseINT int GetBaseINT();
GetBaseAGI int GetBaseAGI();
GetBaseWIS int GetBaseWIS();
GetWeight int GetWeight();
GetEXP uint32 GetEXP();
GetAAExp uint32 GetAAExp();
GetTotalSecondsPlayed uint32 GetTotalSecondsPlayed();
UpdateLDoNPoints void UpdateLDoNPoints(int points, uint32 theme);
SetDeity void SetDeity(int v);
AddEXP void AddEXP(uint32 add_exp, int conlevel = 255, bool resexp = false);
SetEXP void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp = false);
SetBindPoint SetBindPoint(int to_zone = -1, float new_x = 0.0f, float new_y = 0.0f, float new_z = 0.0f);
GetBindX float GetBindX(int index = 0);
GetBindY float GetBindY(int index = 0);
GetBindZ float GetBindZ(int index = 0);
GetBindHeading float GetBindHeading(int index = 0);
GetBindZoneID uint32 GetBindZoneID(int index = 0);
MovePC void MovePC(int zone, float x, float y, float z, float heading);
MovePCInstance void MovePCInstance(int zone, int instance, float x, float y, float z, float heading);
ChangeLastName void ChangeLastName(const char *in);
GetFactionLevel int GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 race, uint32 class, uint32 deity, uint32 faction, Lua_NPC npc);
SetFactionLevel void SetFactionLevel(uint32 char_id, uint32 npc_id, int char_class, int char_race, int char_deity);
SetFactionLevel2 void SetFactionLevel2(uint32 char_id, int faction_id, int char_class, int char_race, int char_deity, int value, int temp);
GetRawItemAC int GetRawItemAC();
AccountID uint32 AccountID();
AccountName const char *AccountName();
Admin bool Admin();
CharacterID uint32 CharacterID();
UpdateAdmin int GuildRank();
UpdateWho uint32 GuildID();
GuildRank int GetFace();
GuildID bool TakeMoneyFromPP(uint64 copper, bool update_client = false);
GetFace void AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool update_client = false);
TakeMoneyFromPP bool TGB();
AddMoneyToPP int GetSkillPoints();
TGB void SetSkillPoints(int skill);
GetSkillPoints void IncreaseSkill(int skill_id, int value);
SetSkillPoints void IncreaseLanguageSkill(int skill_id, int value);
IncreaseSkill int GetRawSkill(int skill_id);
IncreaseLanguageSkill bool HasSkill(int skill_id);
GetSkill bool CanHaveSkill(int skill_id);
GetRawSkill void SetSkill(int skill_id, int value);
HasSkill void AddSkill(int skill_id, int value);
CanHaveSkill void CheckSpecializeIncrease(int spell_id);
SetSkill void CheckIncreaseSkill(int skill_id, Lua_Mob target, int chance_mod = 0);
AddSkill void SetLanguageSkill(int language, int value);
CheckSpecializeIncrease int MaxSkill(int spell_id);
CheckIncreaseSkill bool IsMedding();
SetLanguageSkill Lua_Client GetDuelTarget();
MaxSkill bool IsDueling();
GMKill void SetDuelTarget(Lua_Client c);
IsMedding void SetDueling(bool v);
GetDuelTarget void ResetAA();
IsDueling void MemSpell(int spell_id, int slot, bool update_client = true);
SetDuelTarget void UnmemSpell(int slot, bool update_client = true);
SetDueling void UnmemSpellAll(bool update_client = true);
ResetAA void ScribeSpell(int spell_id, int slot, bool update_client = true);
MemSpell void UnscribeSpell(int slot, bool update_client = true);
UnmemSpell void UnscribeSpellAll(bool update_client = true);
UnmemSpellAll void UntrainDisc(int slot, bool update_client = true);
ScribeSpell void UntrainDiscAll(bool update_client = true);
UnscribeSpell bool IsSitting();
UnscribeSpellAll void SetFeigned(bool v);
UntrainDisc bool GetFeigned();
UntrainDiscAll bool AutoSplitEnabled();
IsSitting void SetHorseId(int id);
IsBecomeNPC int GetHorseId();
GetBecomeNPCLevel void NukeItem(uint32 item_num, int where_to_check);
SetBecomeNPC void SetTint(int slot_id, uint32 color);
SetBecomeNPCLevel void SetMaterial(int slot_id, uint32 item_id);
LootToStack void Undye(int slot_id);
SetFeigned int GetItemIDAt(int slot_id);
GetFeigned int GetAugmentIDAt(int slot_id, int aug_slot);
AutoSplitEnabled void DeleteItemInInventory(int slot_id, int quantity, bool update_client = true);
SetHorseId void SummonItem(uint32 item_id, int charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0,
GetHorseId uint32 aug5 = 0, bool attuned = false, int to_slot = 30);
NukeItem void SetStats(int type, int value);
SetTint void IncStats(int type, int value);
SetMaterial int DropItem(int slot_id);
Undye void BreakInvis();
GetItemIDAt void LeaveGroup();
GetAugmentIDAt bool IsGrouped();
DeleteItemInInventory bool IsRaidGrouped();
SummonItem bool Hungry();
SetStats bool Thirsty();
IncStats int GetInstrumentMod(int spell_id);
DropItem bool DecreaseByID(uint32 type, int amt);
BreakInvis void Escape();
GetGroup void GoFish();
LeaveGroup void ForageItem(bool guarantee = false);
GetRaid float CalcPriceMod(Lua_Mob other, bool reverse);
IsGrouped void ResetTrade();
IsRaidGrouped bool UseDiscipline(int spell_id, int target_id);
Hungry int GetCharacterFactionLevel(int faction_id);
Thirsty void SetZoneFlag(int zone_id);
GetInstrumentMod void ClearZoneFlag(int zone_id);
DecreaseByID bool HasZoneFlag(int zone_id);
SlotConvert2 void SendZoneFlagInfo(Lua_Client to);
Escape void SetAATitle(const char *title);
RemoveNoRent int GetClientVersion();
GoFish uint32 GetClientVersionBit();
ForageItem void SetTitleSuffix(const char *text);
CalcPriceMod void SetAAPoints(int points);
ResetTrade int GetAAPoints();
UseDiscipline int GetSpentAA();
GetCharacterFactionLevel void AddAAPoints(int points);
SetZoneFlag void RefundAA();
ClearZoneFlag int GetModCharacterFactionLevel(int faction);
HasZoneFlag int GetLDoNWins();
SendZoneFlagInfo int GetLDoNLosses();
LoadZoneFlags int GetLDoNWinsTheme(int theme);
SetAATitle int GetLDoNLossesTheme(int theme);
GetClientVersion Lua_ItemInst GetItemAt(int slot);
GetClientVersionBit int GetStartZone();
SetTitleSuffix void SetStartZone(int zone_id, float x = 0.0f, float y = 0.0f, float z = 0.0f);
SetAAPoints void KeyRingAdd(uint32 item);
GetAAPoints bool KeyRingCheck(uint32 item);
GetSpentAA void AddPVPPoints(uint32 points);
AddAAPoints void AddCrystals(uint32 radiant, uint32 ebon);
RefundAA uint32 GetPVPPoints();
GetModCharacterFactionLevel uint32 GetRadiantCrystals();
GetLDoNWins uint32 GetEbonCrystals();
GetLDoNLosses void ReadBook(const char *text, int type);
GetLDoNWinsTheme void UpdateGroupAAs(int points, uint32 type);
GetLDoNLossesTheme uint32 GetGroupPoints();
GetItemAt uint32 GetRaidPoints();
GetAugmentAt void LearnRecipe(uint32 recipe);
GetStartZone int GetEndurance();
SetStartZone int GetMaxEndurance();
KeyRingAdd int GetEndurancePercent();
KeyRingCheck void SetEndurance(int endur);
AddPVPPoints void SendOPTranslocateConfirm(Lua_Mob caster, int spell_id);
AddCrystals const char *GetIP();
GetPVPPoints void AddLevelBasedExp(int exp_pct, int max_level = 0);
GetRadiantCrystals void IncrementAA(int aa);
GetEbonCrystals MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count = 1);
ReadBook int GetFreeSpellBookSlot(int start = 0);
UpdateGroupAAs int GetSpellBookSlotBySpellID(int spell_id);
GetGroupPoints void UpdateTaskActivity(int task, int activity, int count);
GetRaidPoints void AssignTask(int task, int npc_id);
LearnRecipe void FailTask(int task);
GetEndurance bool IsTaskCompleted(int task);
GetMaxEndurance bool IsTaskActive(int task);
GetEnduranceRatio bool IsTaskActivityActive(int task, int activty);
SetEndurance int GetCorpseCount();
SendOPTranslocateConfirm int GetCorpseID(int corpse);
NPCSpawn int GetCorpseItemAt(int corpse, int slot);
GetIP void AssignToInstance(int instance_id);
AddLevelBasedExp void Freeze();
IncrementAA void UnFreeze();
GetAALevel int GetAggroCount();
MarkCompassLoc uint64 GetCarriedMoney();
ClearCompassMark uint64 GetAllMoney();
GetFreeSpellBookSlot void OpenLFGuildWindow();
GetSpellBookSlotBySpellID void Signal(uint32 id);
UpdateTaskActivity void AddAlternateCurrencyValue(uint32 currency, int amount);
AssignTask void SendWebLink(const char *site);
FailTask bool HasSpellScribed(int spell_id);
IsTaskCompleted void SetAccountFlag(std::string flag, std::string val);
IsTaskActive std::string value GetAccountFlag(std::string flag);
IsTaskActivityActive
GetCorpseCount //unsup features
GetCorpseID Lua_Group GetGroup();
GetCorpseItemAt Lua_Raid GetRaid();
AssignToInstance
Freeze
UnFreeze
GetAggroCount
GetCarriedMoney
GetAllMoney
GetItemInInventory
SetCustomItemData
GetCustomItemData
OpenLFGuildWindow
SignalClient
AddAlternateCurrencyValue
SendWebLink
GetInstanceID
HasSpellScribed
SetAccountFlag
GetAccountFlag
*/ */
}; };

View File

@ -12,20 +12,6 @@ struct Lua_HateList;
class Lua_Item; class Lua_Item;
class Lua_ItemInst; class Lua_ItemInst;
//TODO: Remove the error checking by a flag since this adds significant overhead to each c call
#define Lua_Safe_Call_Void() if(!d_) { return; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Bool() if(!d_) { return false; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Int() if(!d_) { return 0; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Real() if(!d_) { return 0.0; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_String() if(!d_) { return ""; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Entity() if(!d_) { return Lua_Entity(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Mob() if(!d_) { return Lua_Mob(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_NPC() if(!d_) { return Lua_NPC(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Client() if(!d_) { return Lua_Client(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_HateList() if(!d_) { return Lua_HateList(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Item() if(!d_) { return Lua_Item(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_ItemInst() if(!d_) { return Lua_ItemInst(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
namespace luabind { namespace luabind {
struct scope; struct scope;
} }

View File

@ -4,6 +4,10 @@
luabind::scope lua_register_general(); luabind::scope lua_register_general();
luabind::scope lua_register_events(); luabind::scope lua_register_events();
luabind::scope lua_register_faction();
luabind::scope lua_register_slot();
luabind::scope lua_register_material();
luabind::scope lua_register_client_version();
#endif #endif
#endif #endif

View File

@ -5,7 +5,6 @@
#include <luabind/object.hpp> #include <luabind/object.hpp>
#include "masterentity.h" #include "masterentity.h"
#include "lua_entity.h"
#include "lua_item.h" #include "lua_item.h"
Lua_Item::Lua_Item(uint32 item_id) { Lua_Item::Lua_Item(uint32 item_id) {

View File

@ -7,7 +7,6 @@
#include "masterentity.h" #include "masterentity.h"
#include "lua_iteminst.h" #include "lua_iteminst.h"
#include "lua_item.h" #include "lua_item.h"
#include "lua_entity.h"
bool Lua_ItemInst::IsType(int item_class) { bool Lua_ItemInst::IsType(int item_class) {
Lua_Safe_Call_Bool(); Lua_Safe_Call_Bool();

View File

@ -1682,6 +1682,11 @@ int Lua_Mob::GetFlurryChance() {
return self->GetFlurryChance(); return self->GetFlurryChance();
} }
int Lua_Mob::GetSkill(int skill) {
Lua_Safe_Call_Int();
return self->GetSkill(static_cast<SkillType>(skill));
}
luabind::scope lua_register_mob() { luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob") return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@ -1977,7 +1982,8 @@ luabind::scope lua_register_mob() {
.def("SetDisableMelee", (void(Lua_Mob::*)(bool))&Lua_Mob::SetDisableMelee) .def("SetDisableMelee", (void(Lua_Mob::*)(bool))&Lua_Mob::SetDisableMelee)
.def("IsMeleeDisabled", (bool(Lua_Mob::*)(void))&Lua_Mob::IsMeleeDisabled) .def("IsMeleeDisabled", (bool(Lua_Mob::*)(void))&Lua_Mob::IsMeleeDisabled)
.def("SetFlurryChance", (void(Lua_Mob::*)(int))&Lua_Mob::SetFlurryChance) .def("SetFlurryChance", (void(Lua_Mob::*)(int))&Lua_Mob::SetFlurryChance)
.def("GetFlurryChance", (int(Lua_Mob::*)(void))&Lua_Mob::GetFlurryChance); .def("GetFlurryChance", (int(Lua_Mob::*)(void))&Lua_Mob::GetFlurryChance)
.def("GetSkill", (int(Lua_Mob::*)(int))&Lua_Mob::GetSkill);
} }
#endif #endif

View File

@ -336,6 +336,7 @@ public:
bool IsMeleeDisabled(); bool IsMeleeDisabled();
void SetFlurryChance(int value); void SetFlurryChance(int value);
int GetFlurryChance(); int GetFlurryChance();
int GetSkill(int skill_id);
}; };
#endif #endif

View File

@ -806,6 +806,7 @@ void LuaParser::MapFunctions(lua_State *L) {
lua_register_mob(), lua_register_mob(),
lua_register_npc(), lua_register_npc(),
lua_register_client(), lua_register_client(),
lua_register_inventory_where(),
lua_register_iteminst(), lua_register_iteminst(),
lua_register_item(), lua_register_item(),
lua_register_spell(), lua_register_spell(),
@ -946,56 +947,8 @@ void LuaParser::ExportQGlobals(NPC *n, Client *c) {
return; return;
} }
QGlobalCache *npc_c = nullptr;
QGlobalCache *char_c = nullptr;
QGlobalCache *zone_c = nullptr;
uint32 npc_id = 0;
uint32 char_id = 0;
uint32 zone_id = 0;
if(n) {
npc_id = n->GetNPCTypeID();
npc_c = n->GetQGlobals();
}
if(c) {
char_id = c->CharacterID();
char_c = c->GetQGlobals();
}
if(zone) {
zone_id = zone->GetZoneID();
zone_c = zone->GetQGlobals();
}
if(!npc_c && n) {
npc_c = n->CreateQGlobals();
npc_c->LoadByNPCID(npc_id);
}
if(!char_c && c) {
char_c = c->CreateQGlobals();
char_c->LoadByCharID(char_id);
}
if(!zone_c && zone) {
zone_c = zone->CreateQGlobals();
zone_c->LoadByZoneID(zone_id);
zone_c->LoadByGlobalContext();
}
std::list<QGlobal> global_map; std::list<QGlobal> global_map;
if(npc_c) { QGlobalCache::GetQGlobals(global_map, n, c, zone);
QGlobalCache::Combine(global_map, npc_c->GetBucket(), npc_id, char_id, zone_id);
}
if(char_c) {
QGlobalCache::Combine(global_map, char_c->GetBucket(), npc_id, char_id, zone_id);
}
if(zone_c) {
QGlobalCache::Combine(global_map, zone_c->GetBucket(), npc_id, char_id, zone_id);
}
auto iter = global_map.begin(); auto iter = global_map.begin();
while(iter != global_map.end()) { while(iter != global_map.end()) {

View File

@ -2,6 +2,20 @@
#define EQEMU_LUA_PTR_H #define EQEMU_LUA_PTR_H
#ifdef LUA_EQEMU #ifdef LUA_EQEMU
//TODO: Remove the error checking by a flag since this adds significant overhead to each c call
#define Lua_Safe_Call_Void() if(!d_) { return; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Bool() if(!d_) { return false; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Int() if(!d_) { return 0; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Real() if(!d_) { return 0.0; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_String() if(!d_) { return ""; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Entity() if(!d_) { return Lua_Entity(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Mob() if(!d_) { return Lua_Mob(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_NPC() if(!d_) { return Lua_NPC(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Client() if(!d_) { return Lua_Client(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_HateList() if(!d_) { return Lua_HateList(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Item() if(!d_) { return Lua_Item(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_ItemInst() if(!d_) { return Lua_ItemInst(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
template<typename T> template<typename T>
class Lua_Ptr class Lua_Ptr
{ {

View File

@ -2713,33 +2713,6 @@ XS(XS_Client_SetBecomeNPCLevel)
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }
XS(XS_Client_LootToStack); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_LootToStack)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Client::LootToStack(THIS, itemid)");
{
Client * THIS;
bool RETVAL;
uint32 itemid = (uint32)SvUV(ST(1));
if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Client");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->LootToStack(itemid);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_Client_SetFeigned); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_SetFeigned); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_SetFeigned) XS(XS_Client_SetFeigned)
{ {
@ -5854,7 +5827,6 @@ XS(boot_Client)
newXSproto(strcpy(buf, "GetBecomeNPCLevel"), XS_Client_GetBecomeNPCLevel, file, "$"); newXSproto(strcpy(buf, "GetBecomeNPCLevel"), XS_Client_GetBecomeNPCLevel, file, "$");
newXSproto(strcpy(buf, "SetBecomeNPC"), XS_Client_SetBecomeNPC, file, "$$"); newXSproto(strcpy(buf, "SetBecomeNPC"), XS_Client_SetBecomeNPC, file, "$$");
newXSproto(strcpy(buf, "SetBecomeNPCLevel"), XS_Client_SetBecomeNPCLevel, file, "$$"); newXSproto(strcpy(buf, "SetBecomeNPCLevel"), XS_Client_SetBecomeNPCLevel, file, "$$");
newXSproto(strcpy(buf, "LootToStack"), XS_Client_LootToStack, file, "$$");
newXSproto(strcpy(buf, "SetFeigned"), XS_Client_SetFeigned, file, "$$"); newXSproto(strcpy(buf, "SetFeigned"), XS_Client_SetFeigned, file, "$$");
newXSproto(strcpy(buf, "GetFeigned"), XS_Client_GetFeigned, file, "$"); newXSproto(strcpy(buf, "GetFeigned"), XS_Client_GetFeigned, file, "$");
newXSproto(strcpy(buf, "AutoSplitEnabled"), XS_Client_AutoSplitEnabled, file, "$"); newXSproto(strcpy(buf, "AutoSplitEnabled"), XS_Client_AutoSplitEnabled, file, "$");