diff --git a/connector/pom.xml b/connector/pom.xml
index 6529dbcd8..9ada540ef 100644
--- a/connector/pom.xml
+++ b/connector/pom.xml
@@ -305,6 +305,7 @@
String GIT_VERSION = ".*"
+
String GIT_VERSION = "git-${git.branch}-${git.commit.id.abbrev}"
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java
index a417a207f..b1427a864 100644
--- a/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java
+++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java
@@ -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;
@@ -67,6 +71,10 @@ public class TagCache {
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 itemTags = packet.getTags().get("minecraft:item");
this.flowers = IntList.of(itemTags.get("minecraft:flowers"));
this.foxFood = IntList.of(itemTags.get("minecraft:fox_food"));
@@ -82,6 +90,10 @@ public class TagCache {
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();
@@ -119,4 +131,16 @@ public class TagCache {
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());
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java
index 109aa1564..4dc87d5d8 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java
@@ -83,11 +83,36 @@ public class BlockUtils {
}
}
- //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) {
@@ -125,11 +150,13 @@ public class BlockUtils {
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;
@@ -137,12 +164,12 @@ public class BlockUtils {
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();
@@ -152,7 +179,7 @@ public class BlockUtils {
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);
}