Fix for unreliable packets (kind of a hack but it works) being flagged as corrupt

This commit is contained in:
KimLS 2017-03-20 00:22:50 -07:00
parent db210ba70e
commit cfdbca6f12
10 changed files with 56 additions and 61 deletions

View File

@ -837,6 +837,11 @@ bool EQ::Net::DaybreakConnection::PacketCanBeEncoded(Packet &p) const
return false; return false;
} }
auto zero = p.GetInt8(0);
if (zero != 0) {
return true;
}
auto opcode = p.GetInt8(1); auto opcode = p.GetInt8(1);
if (opcode == OP_SessionRequest || opcode == OP_SessionResponse || opcode == OP_OutOfSession) { if (opcode == OP_SessionRequest || opcode == OP_SessionResponse || opcode == OP_OutOfSession) {
return false; return false;
@ -1177,7 +1182,16 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
if (PacketCanBeEncoded(p)) { if (PacketCanBeEncoded(p)) {
DynamicPacket out; DynamicPacket out;
out.PutPacket(0, p);
if (p.GetUInt8(0) != 0) {
out.PutUInt8(0, 0);
out.PutUInt8(1, OP_Combined);
out.PutUInt8(2, p.Length());
out.PutPacket(3, p);
}
else {
out.PutPacket(0, p);
}
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
switch (m_encode_passes[i]) { switch (m_encode_passes[i]) {
@ -1242,7 +1256,7 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable) void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable)
{ {
if (!reliable) { if (!reliable) {
auto max_raw_size = m_max_packet_size - m_crc_bytes; auto max_raw_size = 0xFFU - m_crc_bytes;
if (p.Length() > max_raw_size) { if (p.Length() > max_raw_size) {
InternalQueuePacket(p, stream_id, true); InternalQueuePacket(p, stream_id, true);
return; return;

View File

@ -221,8 +221,8 @@ 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 = 384; hold_size = 448;
hold_length_ms = 10; hold_length_ms = 25;
simulated_in_packet_loss = 0; simulated_in_packet_loss = 0;
simulated_out_packet_loss = 0; simulated_out_packet_loss = 0;
tic_rate_hertz = 60.0; tic_rate_hertz = 60.0;

View File

@ -81,7 +81,10 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
break; break;
} }
m_connection->QueuePacket(out); if (ack_req)
m_connection->QueuePacket(out);
else
m_connection->QueuePacket(out, 0, false);
} }
} }

View File

@ -136,7 +136,7 @@ bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const
if (Hand == EQEmu::inventory::slotSecondary) // DW anim if (Hand == EQEmu::inventory::slotSecondary) // DW anim
type = animDualWield; type = animDualWield;
DoAnim(type); DoAnim(type, 0, false);
return true; return true;
} }

View File

@ -8647,7 +8647,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
if (exp > 0) if (exp > 0)
AddEXP(exp); AddEXP(exp);
QueuePacket(outapp, false, Client::CLIENT_CONNECTED); QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
safe_delete(outapp); safe_delete(outapp);
} }

View File

@ -4484,7 +4484,7 @@ void Merc::DoClassAttacks(Mob *target) {
if(level >= RuleI(Combat, NPCBashKickLevel)){ if(level >= RuleI(Combat, NPCBashKickLevel)){
if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
{ {
DoAnim(animKick); DoAnim(animKick, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@ -4496,7 +4496,7 @@ void Merc::DoClassAttacks(Mob *target) {
} }
else else
{ {
DoAnim(animTailRake); DoAnim(animTailRake, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)

View File

@ -2131,7 +2131,7 @@ void Mob::SendTargetable(bool on, Client *specific_target) {
entity_list.QueueClients(this, outapp); entity_list.QueueClients(this, outapp);
} }
else if (specific_target->IsClient()) { else if (specific_target->IsClient()) {
specific_target->CastToClient()->QueuePacket(outapp, false); specific_target->CastToClient()->QueuePacket(outapp);
} }
safe_delete(outapp); safe_delete(outapp);
} }

View File

@ -345,7 +345,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
} }
bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) {
if((iSpellTypes&SpellTypes_Detrimental) != 0) { if((iSpellTypes & SpellTypes_Detrimental) != 0) {
//according to live, you can buff and heal through walls... //according to live, you can buff and heal through walls...
//now with PCs, this only applies if you can TARGET the target, but //now with PCs, this only applies if you can TARGET the target, but
// according to Rogean, Live NPCs will just cast through walls/floors, no problem.. // according to Rogean, Live NPCs will just cast through walls/floors, no problem..
@ -374,41 +374,19 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
float iRange2 = iRange*iRange; float iRange2 = iRange*iRange;
float t1, t2, t3;
//Only iterate through NPCs //Only iterate through NPCs
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) { for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
NPC* mob = it->second; NPC* mob = it->second;
//Since >90% of mobs will always be out of range, try to if (mob->GetReverseFactionCon(caster) >= FACTION_KINDLY) {
//catch them with simple bounding box checks first. These
//checks are about 6X faster than DistNoRoot on my athlon 1Ghz
t1 = mob->GetX() - caster->GetX();
t2 = mob->GetY() - caster->GetY();
t3 = mob->GetZ() - caster->GetZ();
//cheap ABS()
if(t1 < 0)
t1 = 0 - t1;
if(t2 < 0)
t2 = 0 - t2;
if(t3 < 0)
t3 = 0 - t3;
if (t1 > iRange
|| t2 > iRange
|| t3 > iRange
|| DistanceSquared(mob->GetPosition(), caster->GetPosition()) > iRange2
//this call should seem backwards:
|| !mob->CheckLosFN(caster)
|| mob->GetReverseFactionCon(caster) >= FACTION_KINDLY
) {
continue; continue;
} }
//since we assume these are beneficial spells, which do not if (DistanceSquared(caster->GetPosition(), mob->GetPosition()) > iRange2) {
//require LOS, we just go for it. continue;
// we have a winner! }
if((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)){
if ((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)) {
if (mob != caster) if (mob != caster)
iSpellTypes = SpellType_Heal; iSpellTypes = SpellType_Heal;
} }

View File

@ -435,7 +435,7 @@ int main(int argc, char** argv) {
std::unique_ptr<EQ::Net::EQStreamManager> eqsm; std::unique_ptr<EQ::Net::EQStreamManager> eqsm;
std::chrono::time_point<std::chrono::system_clock> frame_prev = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> frame_prev = std::chrono::system_clock::now();
EQ::Timer process_timer(15, true, [&](EQ::Timer* t) { EQ::Timer process_timer(32, true, [&](EQ::Timer* t) {
//Advance the timer to our current point in time //Advance the timer to our current point in time
Timer::SetCurrentTime(); Timer::SetCurrentTime();
@ -447,7 +447,7 @@ int main(int argc, char** argv) {
if (!eqsf_open && Config->ZonePort != 0) { if (!eqsf_open && Config->ZonePort != 0) {
Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort); Log.Out(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort);
EQ::Net::EQStreamManagerOptions opts(Config->ZonePort, false, false); EQ::Net::EQStreamManagerOptions opts(Config->ZonePort, false, true);
eqsm.reset(new EQ::Net::EQStreamManager(opts)); eqsm.reset(new EQ::Net::EQStreamManager(opts));
eqsf_open = true; eqsf_open = true;

View File

@ -302,7 +302,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
if (GetTarget() != this) { if (GetTarget() != this) {
CheckIncreaseSkill(EQEmu::skills::SkillBash, GetTarget(), 10); CheckIncreaseSkill(EQEmu::skills::SkillBash, GetTarget(), 10);
DoAnim(animTailRake); DoAnim(animTailRake, 0, false);
int32 ht = 0; int32 ht = 0;
if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 &&
@ -324,7 +324,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10);
int AtkRounds = 1; int AtkRounds = 1;
int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy, GetTarget()); int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy, GetTarget());
DoAnim(anim2HSlashing); DoAnim(anim2HSlashing, 0, false);
max_dmg = mod_frenzy_damage(max_dmg); max_dmg = mod_frenzy_damage(max_dmg);
@ -359,7 +359,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
break; break;
if (GetTarget() != this) { if (GetTarget() != this) {
CheckIncreaseSkill(EQEmu::skills::SkillKick, GetTarget(), 10); CheckIncreaseSkill(EQEmu::skills::SkillKick, GetTarget(), 10);
DoAnim(animKick); DoAnim(animKick, 0, false);
int32 ht = 0; int32 ht = 0;
if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0) if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0)
@ -452,40 +452,40 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type)
skill_type = EQEmu::skills::SkillFlyingKick; skill_type = EQEmu::skills::SkillFlyingKick;
max_dmg = GetBaseSkillDamage(skill_type); max_dmg = GetBaseSkillDamage(skill_type);
min_dmg = 0; // revamped FK formula is missing the min mod? min_dmg = 0; // revamped FK formula is missing the min mod?
DoAnim(animFlyingKick); DoAnim(animFlyingKick, 0, false);
reuse = FlyingKickReuseTime; reuse = FlyingKickReuseTime;
break; break;
case EQEmu::skills::SkillDragonPunch: case EQEmu::skills::SkillDragonPunch:
skill_type = EQEmu::skills::SkillDragonPunch; skill_type = EQEmu::skills::SkillDragonPunch;
max_dmg = GetBaseSkillDamage(skill_type); max_dmg = GetBaseSkillDamage(skill_type);
itemslot = EQEmu::inventory::slotHands; itemslot = EQEmu::inventory::slotHands;
DoAnim(animTailRake); DoAnim(animTailRake, 0, false);
reuse = TailRakeReuseTime; reuse = TailRakeReuseTime;
break; break;
case EQEmu::skills::SkillEagleStrike: case EQEmu::skills::SkillEagleStrike:
skill_type = EQEmu::skills::SkillEagleStrike; skill_type = EQEmu::skills::SkillEagleStrike;
max_dmg = GetBaseSkillDamage(skill_type); max_dmg = GetBaseSkillDamage(skill_type);
itemslot = EQEmu::inventory::slotHands; itemslot = EQEmu::inventory::slotHands;
DoAnim(animEagleStrike); DoAnim(animEagleStrike, 0, false);
reuse = EagleStrikeReuseTime; reuse = EagleStrikeReuseTime;
break; break;
case EQEmu::skills::SkillTigerClaw: case EQEmu::skills::SkillTigerClaw:
skill_type = EQEmu::skills::SkillTigerClaw; skill_type = EQEmu::skills::SkillTigerClaw;
max_dmg = GetBaseSkillDamage(skill_type); max_dmg = GetBaseSkillDamage(skill_type);
itemslot = EQEmu::inventory::slotHands; itemslot = EQEmu::inventory::slotHands;
DoAnim(animTigerClaw); DoAnim(animTigerClaw, 0, false);
reuse = TigerClawReuseTime; reuse = TigerClawReuseTime;
break; break;
case EQEmu::skills::SkillRoundKick: case EQEmu::skills::SkillRoundKick:
skill_type = EQEmu::skills::SkillRoundKick; skill_type = EQEmu::skills::SkillRoundKick;
max_dmg = GetBaseSkillDamage(skill_type); max_dmg = GetBaseSkillDamage(skill_type);
DoAnim(animRoundKick); DoAnim(animRoundKick, 0, false);
reuse = RoundKickReuseTime; reuse = RoundKickReuseTime;
break; break;
case EQEmu::skills::SkillKick: case EQEmu::skills::SkillKick:
skill_type = EQEmu::skills::SkillKick; skill_type = EQEmu::skills::SkillKick;
max_dmg = GetBaseSkillDamage(skill_type); max_dmg = GetBaseSkillDamage(skill_type);
DoAnim(animKick); DoAnim(animKick, 0, false);
reuse = KickReuseTime; reuse = KickReuseTime;
break; break;
default: default:
@ -604,7 +604,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
hate = base_damage; hate = base_damage;
DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime); DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime);
DoAnim(anim1HPiercing); DoAnim(anim1HPiercing, 0, false);
} }
// assassinate [No longer used for regular assassinate 6-29-14] // assassinate [No longer used for regular assassinate 6-29-14]
@ -617,7 +617,7 @@ void Mob::RogueAssassinate(Mob* other)
}else{ }else{
other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab);
} }
DoAnim(anim1HPiercing); //piercing animation DoAnim(anim1HPiercing, 0, false); //piercing animation
} }
void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
@ -1595,7 +1595,7 @@ void NPC::DoClassAttacks(Mob *target) {
case WARRIOR: case WARRIORGM:{ case WARRIOR: case WARRIORGM:{
if(level >= RuleI(Combat, NPCBashKickLevel)){ if(level >= RuleI(Combat, NPCBashKickLevel)){
if(zone->random.Roll(75)) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. if(zone->random.Roll(75)) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
DoAnim(animKick); DoAnim(animKick, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@ -1606,7 +1606,7 @@ void NPC::DoClassAttacks(Mob *target) {
did_attack = true; did_attack = true;
} }
else { else {
DoAnim(animTailRake); DoAnim(animTailRake, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@ -1622,7 +1622,7 @@ void NPC::DoClassAttacks(Mob *target) {
case BERSERKER: case BERSERKERGM:{ case BERSERKER: case BERSERKERGM:{
int AtkRounds = 1; int AtkRounds = 1;
int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy); int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy);
DoAnim(anim2HSlashing); DoAnim(anim2HSlashing, 0, false);
if (GetClass() == BERSERKER) { if (GetClass() == BERSERKER) {
int chance = GetLevel() * 2 + GetSkill(EQEmu::skills::SkillFrenzy); int chance = GetLevel() * 2 + GetSkill(EQEmu::skills::SkillFrenzy);
@ -1645,7 +1645,7 @@ void NPC::DoClassAttacks(Mob *target) {
case BEASTLORD: case BEASTLORDGM: { case BEASTLORD: case BEASTLORDGM: {
//kick //kick
if(level >= RuleI(Combat, NPCBashKickLevel)){ if(level >= RuleI(Combat, NPCBashKickLevel)){
DoAnim(animKick); DoAnim(animKick, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@ -1661,7 +1661,7 @@ void NPC::DoClassAttacks(Mob *target) {
case SHADOWKNIGHT: case SHADOWKNIGHTGM: case SHADOWKNIGHT: case SHADOWKNIGHTGM:
case PALADIN: case PALADINGM:{ case PALADIN: case PALADINGM:{
if(level >= RuleI(Combat, NPCBashKickLevel)){ if(level >= RuleI(Combat, NPCBashKickLevel)){
DoAnim(animTailRake); DoAnim(animTailRake, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@ -1760,7 +1760,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill_to_use == EQEmu::skills::SkillBash) { if (skill_to_use == EQEmu::skills::SkillBash) {
if (ca_target!=this) { if (ca_target!=this) {
DoAnim(animTailRake); DoAnim(animTailRake, 0, false);
if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0) if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0)
dmg = DMG_INVULNERABLE; dmg = DMG_INVULNERABLE;
@ -1779,7 +1779,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill_to_use == EQEmu::skills::SkillFrenzy) { if (skill_to_use == EQEmu::skills::SkillFrenzy) {
CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10);
int AtkRounds = 1; int AtkRounds = 1;
DoAnim(anim2HSlashing); DoAnim(anim2HSlashing, 0, false);
ReuseTime = (FrenzyReuseTime - 1) / HasteMod; ReuseTime = (FrenzyReuseTime - 1) / HasteMod;
@ -1806,7 +1806,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill_to_use == EQEmu::skills::SkillKick){ if (skill_to_use == EQEmu::skills::SkillKick){
if(ca_target!=this){ if(ca_target!=this){
DoAnim(animKick); DoAnim(animKick, 0, false);
if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0) if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0)
dmg = DMG_INVULNERABLE; dmg = DMG_INVULNERABLE;