1
0

Fix instant mining of blocks not being recognised, tweak anti-cheat (#4938)

* Tried to fix a small issue...

Ended up rewriting a bunch of god awful, opaque code with no source
and no sense. Who names a function GetPlayerRelativeBlockHardness???
It's gone now. We're safe again.

* Testing anti-cheat.

* Tidy up debug logging.

* Remove empty member declaration.

* Rewrite GetDigSpeed slightly for better readability.

* GetMiningProgressPerTick now returns 1 when instantly mined. Fixed hasily written typo.

* Comment style and typo fixes.
This commit is contained in:
KingCol13
2020-10-02 23:57:17 +03:00
committed by GitHub
parent 89fb16fc27
commit cd1b507745
6 changed files with 109 additions and 49 deletions

View File

@@ -3156,61 +3156,109 @@ bool cPlayer::IsInsideWater()
float cPlayer::GetDigSpeed(BLOCKTYPE a_Block)
{
float f = GetEquippedItem().GetHandler()->GetBlockBreakingStrength(a_Block);
if (f > 1.0f)
// Based on: https://minecraft.gamepedia.com/Breaking#Speed
// Get the base speed multiplier of the equipped tool for the mined block
float MiningSpeed = GetEquippedItem().GetHandler()->GetBlockBreakingStrength(a_Block);
// If we can harvest the block then we can apply material and enchantment bonuses
if (GetEquippedItem().GetHandler()->CanHarvestBlock(a_Block))
{
unsigned int efficiencyModifier = GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchEfficiency);
if (efficiencyModifier > 0)
if (MiningSpeed > 1.0f) // If the base multiplier for this block is greater than 1, now we can check enchantments
{
f += (efficiencyModifier * efficiencyModifier) + 1;
unsigned int EfficiencyModifier = GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchEfficiency);
if (EfficiencyModifier > 0) // If an efficiency enchantment is present, apply formula as on wiki
{
MiningSpeed += (EfficiencyModifier * EfficiencyModifier) + 1;
}
}
}
else // If we can't harvest the block then no bonuses:
{
MiningSpeed = 1;
}
// Haste increases speed by 20% per level
auto Haste = GetEntityEffect(cEntityEffect::effHaste);
if (Haste != nullptr)
{
int intensity = Haste->GetIntensity() + 1;
f *= 1.0f + (intensity * 0.2f);
MiningSpeed *= 1.0f + (intensity * 0.2f);
}
// Mining fatigue decreases speed a lot
auto MiningFatigue = GetEntityEffect(cEntityEffect::effMiningFatigue);
if (MiningFatigue != nullptr)
{
int intensity = MiningFatigue->GetIntensity();
switch (intensity)
{
case 0: f *= 0.3f; break;
case 1: f *= 0.09f; break;
case 2: f *= 0.0027f; break;
default: f *= 0.00081f; break;
case 0: MiningSpeed *= 0.3f; break;
case 1: MiningSpeed *= 0.09f; break;
case 2: MiningSpeed *= 0.0027f; break;
default: MiningSpeed *= 0.00081f; break;
}
}
// 5x speed loss for being in water
if (IsInsideWater() && !(GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchAquaAffinity) > 0))
{
f /= 5.0f;
MiningSpeed /= 5.0f;
}
// 5x speed loss for not touching ground
if (!IsOnGround())
{
f /= 5.0f;
MiningSpeed /= 5.0f;
}
return f;
return MiningSpeed;
}
float cPlayer::GetPlayerRelativeBlockHardness(BLOCKTYPE a_Block)
float cPlayer::GetMiningProgressPerTick(BLOCKTYPE a_Block)
{
float blockHardness = cBlockInfo::GetHardness(a_Block);
float digSpeed = GetDigSpeed(a_Block);
float canHarvestBlockDivisor = GetEquippedItem().GetHandler()->CanHarvestBlock(a_Block) ? 30.0f : 100.0f;
// LOGD("blockHardness: %f, digSpeed: %f, canHarvestBlockDivisor: %f\n", blockHardness, digSpeed, canHarvestBlockDivisor);
return (blockHardness < 0) ? 0 : ((digSpeed / blockHardness) / canHarvestBlockDivisor);
// Based on https://minecraft.gamepedia.com/Breaking#Calculation
// If we know it's instantly breakable then quit here:
if (cBlockInfo::IsOneHitDig(a_Block))
{
return 1;
}
float BlockHardness = cBlockInfo::GetHardness(a_Block);
ASSERT(BlockHardness > 0); // Can't divide by 0 or less, IsOneHitDig should have returned true
if (GetEquippedItem().GetHandler()->CanHarvestBlock(a_Block))
{
BlockHardness*=1.5;
}
else
{
BlockHardness*=5;
}
float DigSpeed = GetDigSpeed(a_Block);
// LOGD("Time to mine block = %f", BlockHardness/DigSpeed);
// Number of ticks to mine = (20 * BlockHardness)/DigSpeed;
// Therefore take inverse to get fraction mined per tick:
return DigSpeed / (20 * BlockHardness);
}
bool cPlayer::CanInstantlyMine(BLOCKTYPE a_Block)
{
// Based on: https://minecraft.gamepedia.com/Breaking#Calculation
// Check it has non-zero hardness
if (cBlockInfo::IsOneHitDig(a_Block))
{
return true;
}
// If the dig speed is greater than 30 times the hardness, then the wiki says we can instantly mine
return GetDigSpeed(a_Block) > 30 * cBlockInfo::GetHardness(a_Block);
}