Skip to content

Commit

Permalink
Respect tool tier requirement for block breaking (GeyserMC#1837)
Browse files Browse the repository at this point in the history
  • Loading branch information
Camotoy committed May 24, 2021
1 parent 986701f commit 1f83a5a
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
1 change: 1 addition & 0 deletions connector/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
</replacement>
<replacement>
<token>String GIT_VERSION = ".*"</token>
<!--suppress UnresolvedMavenProperty -->
<value>String GIT_VERSION = "git-${git.branch}-${git.commit.id.abbrev}"</value>
</replacement>
</replacements>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public class TagCache {
private IntList pickaxeEffective;
private IntList shovelEffective;

private IntList requiresStoneTool;
private IntList requiresIronTool;
private IntList requiresDiamondTool;

/* Items */
private IntList flowers;
private IntList foxFood;
Expand All @@ -67,6 +71,10 @@ public void loadPacket(ServerDeclareTagsPacket packet) {
this.pickaxeEffective = IntList.of(blockTags.get("minecraft:mineable/pickaxe"));
this.shovelEffective = IntList.of(blockTags.get("minecraft:mineable/shovel"));

this.requiresStoneTool = IntList.of(blockTags.get("minecraft:needs_stone_tool"));
this.requiresIronTool = IntList.of(blockTags.get("minecraft:needs_iron_tool"));
this.requiresDiamondTool = IntList.of(blockTags.get("minecraft:needs_diamond_tool"));

Map<String, int[]> itemTags = packet.getTags().get("minecraft:item");
this.flowers = IntList.of(itemTags.get("minecraft:flowers"));
this.foxFood = IntList.of(itemTags.get("minecraft:fox_food"));
Expand All @@ -82,6 +90,10 @@ public void clear() {
this.pickaxeEffective = IntLists.emptyList();
this.shovelEffective = IntLists.emptyList();

this.requiresStoneTool = IntLists.emptyList();
this.requiresIronTool = IntLists.emptyList();
this.requiresDiamondTool = IntLists.emptyList();

this.flowers = IntLists.emptyList();
this.foxFood = IntLists.emptyList();
this.piglinLoved = IntLists.emptyList();
Expand Down Expand Up @@ -119,4 +131,16 @@ public boolean isShearsEffective(BlockMapping blockMapping) {
int javaBlockId = blockMapping.getJavaBlockId();
return leaves.contains(javaBlockId) || wool.contains(javaBlockId);
}

public boolean requiresStoneTool(BlockMapping blockMapping) {
return requiresStoneTool.contains(blockMapping.getJavaBlockId());
}

public boolean requiresIronTool(BlockMapping blockMapping) {
return requiresIronTool.contains(blockMapping.getJavaBlockId());
}

public boolean requiresDiamondTool(BlockMapping blockMapping) {
return requiresDiamondTool.contains(blockMapping.getJavaBlockId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,36 @@ private static double toolBreakTimeBonus(String toolType, String toolTier, boole
}
}

//http://minecraft.gamepedia.com/Breaking
private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool,
private static boolean canToolTierBreakBlock(GeyserSession session, BlockMapping blockMapping, String toolTier) {
if (toolTier.equals("netherite") || toolTier.equals("diamond")) {
// As of 1.17, these tiers can mine everything that is mineable
return true;
}

switch (toolTier) {
// Use intentional fall-throughs to check each tier with this block
default:
if (session.getTagCache().requiresStoneTool(blockMapping)) {
return false;
}
case "stone":
if (session.getTagCache().requiresIronTool(blockMapping)) {
return false;
}
case "iron":
if (session.getTagCache().requiresDiamondTool(blockMapping)) {
return false;
}
}

return true;
}

// https://minecraft.gamepedia.com/Breaking
private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool, boolean canTierMineBlock,
String toolType, boolean isShearsEffective, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel,
boolean insideOfWaterWithoutAquaAffinity, boolean outOfWaterButNotOnGround, boolean insideWaterAndNotOnGround) {
double baseTime = ((correctTool || canHarvestWithHand) ? 1.5 : 5.0) * blockHardness;
double baseTime = (((correctTool && canTierMineBlock) || canHarvestWithHand) ? 1.5 : 5.0) * blockHardness;
double speed = 1.0 / baseTime;

if (correctTool) {
Expand Down Expand Up @@ -125,24 +150,26 @@ public static double getBreakTime(GeyserSession session, BlockMapping blockMappi
String toolType = "";
String toolTier = "";
boolean correctTool = false;
boolean toolCanBreak = false;
if (item instanceof ToolItemEntry) {
ToolItemEntry toolItem = (ToolItemEntry) item;
toolType = toolItem.getToolType();
toolTier = toolItem.getToolTier();
correctTool = correctTool(session, blockMapping, toolType);
toolCanBreak = canToolTierBreakBlock(session, blockMapping, toolTier);
}
int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(nbtData, "minecraft:efficiency");
int hasteLevel = 0;
int miningFatigueLevel = 0;

if (!isSessionPlayer) {
// Another entity is currently mining; we have all the information we know
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isShearsEffective,
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false,
false, false);
}

hasteLevel = session.getEffectCache().getEffectLevel(Effect.FASTER_DIG);
hasteLevel = Math.max(session.getEffectCache().getEffectLevel(Effect.FASTER_DIG), session.getEffectCache().getEffectLevel(Effect.CONDUIT_POWER));
miningFatigueLevel = session.getEffectCache().getEffectLevel(Effect.SLOWER_DIG);

boolean isInWater = session.getCollisionManager().isPlayerInWater();
Expand All @@ -152,7 +179,7 @@ public static double getBreakTime(GeyserSession session, BlockMapping blockMappi

boolean outOfWaterButNotOnGround = (!isInWater) && (!session.getPlayerEntity().isOnGround());
boolean insideWaterNotOnGround = isInWater && !session.getPlayerEntity().isOnGround();
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isShearsEffective,
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity,
outOfWaterButNotOnGround, insideWaterNotOnGround);
}
Expand Down

0 comments on commit 1f83a5a

Please sign in to comment.