Skip to content

Commit 0d22e34

Browse files
committed
refactor BlockBreakSpeed class for improved maintainability
1 parent 2d053d0 commit 0d22e34

File tree

1 file changed

+158
-128
lines changed

1 file changed

+158
-128
lines changed

common/src/main/java/ac/grim/grimac/utils/nmsutil/BlockBreakSpeed.java

Lines changed: 158 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,23 @@ public class BlockBreakSpeed {
5454
StateTypes.ENDER_CHEST
5555
);
5656

57-
private static final boolean serverUsesComponentsAndRules = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_5);
57+
private static final boolean SERVER_USES_COMPONENTS_AND_RULES = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_5);
58+
59+
record ToolSpeedData(float speedMultiplier, boolean isCorrectToolForDrop) {
60+
}
5861

5962
public static double getBlockDamage(GrimPlayer player, WrappedBlockState block) {
63+
ItemStack tool = player.inventory.getHeldItem();
64+
return getBlockDamage(player, tool, block.getType());
65+
}
66+
67+
public static double getBlockDamage(GrimPlayer player, ItemStack tool, StateType block) {
6068
// GET destroy speed
6169
// Starts with itemstack get destroy speed
62-
ItemStack tool = player.inventory.getHeldItem();
6370
ItemType toolType = tool.getType();
6471

6572
if (player.gamemode == GameMode.CREATIVE) {
66-
if (serverUsesComponentsAndRules && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_5)) {
73+
if (SERVER_USES_COMPONENTS_AND_RULES && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_5)) {
6774
return tool.getComponent(ComponentTypes.TOOL)
6875
.map(ItemTool::isCanDestroyBlocksInCreative)
6976
.orElse(true) ? 1 : 0;
@@ -77,137 +84,35 @@ public static double getBlockDamage(GrimPlayer player, WrappedBlockState block)
7784
}
7885
}
7986

80-
float blockHardness = block.getType().getHardness();
87+
float blockHardness = block.getHardness();
8188

8289
// 1.15.2 and below need this hack
83-
if ((block.getType() == StateTypes.PISTON || block.getType() == StateTypes.PISTON_HEAD || block.getType() == StateTypes.STICKY_PISTON) && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2)) {
90+
if ((block == StateTypes.PISTON || block == StateTypes.PISTON_HEAD || block == StateTypes.STICKY_PISTON) && player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_15_2)) {
8491
blockHardness = 0.5f;
8592
}
8693

8794
if (blockHardness == -1) return 0; // Unbreakable block
8895

89-
boolean isCorrectToolForDrop = false;
90-
float speedMultiplier = 1.0F;
91-
92-
// TODO technically its possible to use packet level manipulation to enforce Tool rules on newer clients on older servers
93-
// But I've yet to hear of anyone even trying to do such a thing rather than just update the server
94-
// And we can't support this because we don't see the tool components/data before Via
95-
if (serverUsesComponentsAndRules && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)) {
96-
Optional<ItemTool> toolComponentOpt = tool.getComponent(ComponentTypes.TOOL);
97-
if (toolComponentOpt.isPresent()) {
98-
ItemTool itemTool = toolComponentOpt.get();
99-
100-
// Initialize with final default values. These will be used if the loop doesn't find a value.
101-
// isCorrectToolForDrop is already set to false, no need to set again as default
102-
speedMultiplier = itemTool.getDefaultMiningSpeed();
103-
104-
boolean speedFound = false;
105-
boolean dropsFound = false;
106-
107-
for (ItemTool.Rule rule : itemTool.getRules()) {
108-
MappedEntitySet<StateType.Mapped> predicate = rule.getBlocks();
109-
ResourceLocation tagKey = predicate.getTagKey();
110-
boolean isMatch;
111-
112-
// First, determine if the current rule even applies to this block.
113-
if (tagKey != null) {
114-
SyncedTag<StateType> playerTag = player.tagManager.block(tagKey);
115-
isMatch = (playerTag != null && playerTag.contains(block.getType()))
116-
|| BlockTags.getByName(tagKey.getKey()).contains(block.getType());
117-
} else {
118-
isMatch = predicate.getEntities().contains(block.getType().getMapped());
119-
}
120-
121-
// If the rule matches the block, check if we still need its properties.
122-
if (isMatch) {
123-
// Check for speed if we haven't found it yet.
124-
if (!speedFound && rule.getSpeed() != null) {
125-
speedMultiplier = rule.getSpeed();
126-
speedFound = true;
127-
}
128-
129-
// Check for drops if we haven't found it yet.
130-
if (!dropsFound && rule.getCorrectForDrops() != null) {
131-
isCorrectToolForDrop = rule.getCorrectForDrops();
132-
dropsFound = true;
133-
}
134-
}
135-
136-
if (speedFound && dropsFound) {
137-
break;
138-
}
139-
}
140-
}
96+
final ToolSpeedData toolSpeedData;
97+
if (SERVER_USES_COMPONENTS_AND_RULES && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)) {
98+
toolSpeedData = getModernToolSpeedData(player, tool, block);
14199
} else {
142-
// 1.13 and below need their own huge methods to support this...
143-
if (toolType.hasAttribute(ItemTypes.ItemAttribute.AXE)) {
144-
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_AXE).contains(block.getType());
145-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.PICKAXE)) {
146-
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_PICKAXE).contains(block.getType());
147-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.SHOVEL)) {
148-
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_SHOVEL).contains(block.getType());
149-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.HOE)) {
150-
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_HOE).contains(block.getType());
151-
}
152-
153-
if (isCorrectToolForDrop) {
154-
int tier = 0;
155-
if (toolType.hasAttribute(ItemTypes.ItemAttribute.WOOD_TIER)) { // Tier 0
156-
speedMultiplier = 2.0f;
157-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.STONE_TIER)) { // Tier 1
158-
speedMultiplier = 4.0f;
159-
tier = 1;
160-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.IRON_TIER)) { // Tier 2
161-
speedMultiplier = 6.0f;
162-
tier = 2;
163-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.DIAMOND_TIER)) { // Tier 3
164-
speedMultiplier = 8.0f;
165-
tier = 3;
166-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.GOLD_TIER)) { // Tier 0
167-
speedMultiplier = 12.0f;
168-
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.NETHERITE_TIER)) { // Tier 4
169-
speedMultiplier = 9.0f;
170-
tier = 4;
171-
}
100+
toolSpeedData = getLegacyToolSpeedData(player, tool, block);
101+
}
172102

173-
if (tier < 3 && player.tagManager.block(SyncedTags.NEEDS_DIAMOND_TOOL).contains(block.getType())) {
174-
isCorrectToolForDrop = false;
175-
} else if (tier < 2 && player.tagManager.block(SyncedTags.NEEDS_IRON_TOOL).contains(block.getType())) {
176-
isCorrectToolForDrop = false;
177-
} else if (tier < 1 && player.tagManager.block(SyncedTags.NEEDS_STONE_TOOL).contains(block.getType())) {
178-
isCorrectToolForDrop = false;
179-
}
180-
}
103+
final float speedMultiplier = getSpeedMultiplierFromToolData(player, tool, toolSpeedData);
181104

182-
// Shears can mine some blocks faster
183-
if (toolType == ItemTypes.SHEARS) {
184-
isCorrectToolForDrop = true;
185-
186-
if (block.getType() == StateTypes.COBWEB || Materials.isLeaves(block.getType())) {
187-
speedMultiplier = 15.0f;
188-
} else if (BlockTags.WOOL.contains(block.getType())) {
189-
speedMultiplier = 5.0f;
190-
} else if (block.getType() == StateTypes.VINE ||
191-
block.getType() == StateTypes.GLOW_LICHEN) {
192-
speedMultiplier = 2.0f;
193-
} else {
194-
isCorrectToolForDrop = block.getType() == StateTypes.COBWEB ||
195-
block.getType() == StateTypes.REDSTONE_WIRE ||
196-
block.getType() == StateTypes.TRIPWIRE;
197-
}
198-
}
105+
final boolean canHarvest = !block.isRequiresCorrectTool() || toolSpeedData.isCorrectToolForDrop
106+
// temporary hardcode to workaround PE bug https://github.com/retrooper/packetevents/issues/1217; see https://github.com/GrimAnticheat/Grim/issues/2091
107+
|| player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_4) && HARVESTABLE_TYPES_1_21_4.contains(block);
199108

200-
// Swords can also mine some blocks faster
201-
if (toolType.hasAttribute(ItemTypes.ItemAttribute.SWORD)) {
202-
if (block.getType() == StateTypes.COBWEB) {
203-
speedMultiplier = 15.0f;
204-
} else if (player.tagManager.block(SyncedTags.SWORD_EFFICIENT).contains(block.getType())) {
205-
speedMultiplier = 1.5f;
206-
}
109+
float damage = speedMultiplier / blockHardness;
110+
damage /= canHarvest ? 30F : 100F;
111+
return damage;
112+
}
207113

208-
isCorrectToolForDrop = block.getType() == StateTypes.COBWEB;
209-
}
210-
}
114+
private static float getSpeedMultiplierFromToolData(GrimPlayer player, ItemStack tool, ToolSpeedData data) {
115+
float speedMultiplier = data.speedMultiplier;
211116

212117
if (speedMultiplier > 1.0f) {
213118
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21) && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) {
@@ -262,13 +167,138 @@ public static double getBlockDamage(GrimPlayer player, WrappedBlockState block)
262167
speedMultiplier /= 5;
263168
}
264169

265-
float damage = speedMultiplier / blockHardness;
170+
return speedMultiplier;
171+
}
266172

267-
boolean canHarvest = !block.getType().isRequiresCorrectTool() || isCorrectToolForDrop
268-
// temporary hardcode to workaround PE bug https://github.com/retrooper/packetevents/issues/1217; see https://github.com/GrimAnticheat/Grim/issues/2091
269-
|| player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_4) && HARVESTABLE_TYPES_1_21_4.contains(block.getType());
270-
damage /= canHarvest ? 30F : 100F;
173+
// TODO technically its possible to use packet level manipulation to enforce Tool rules on newer clients on older servers
174+
// But I've yet to hear of anyone even trying to do such a thing rather than just update the server
175+
// And we can't support this because we don't see the tool components/data before Via
176+
private static ToolSpeedData getModernToolSpeedData(GrimPlayer player, ItemStack tool, StateType block) {
177+
Optional<ItemTool> toolComponentOpt = tool.getComponent(ComponentTypes.TOOL);
178+
float speedMultiplier = 1.0f;
179+
boolean isCorrectToolForDrop = false;
180+
if (toolComponentOpt.isPresent()) {
181+
ItemTool itemTool = toolComponentOpt.get();
182+
183+
// Initialize with final default values. These will be used if the loop doesn't find a value.
184+
// isCorrectToolForDrop is already set to false, no need to set again as default
185+
speedMultiplier = itemTool.getDefaultMiningSpeed();
186+
187+
boolean speedFound = false;
188+
boolean dropsFound = false;
189+
190+
for (ItemTool.Rule rule : itemTool.getRules()) {
191+
MappedEntitySet<StateType.Mapped> predicate = rule.getBlocks();
192+
ResourceLocation tagKey = predicate.getTagKey();
193+
boolean isMatch;
194+
195+
// First, determine if the current rule even applies to this block.
196+
if (tagKey != null) {
197+
SyncedTag<StateType> playerTag = player.tagManager.block(tagKey);
198+
isMatch = (playerTag != null && playerTag.contains(block))
199+
|| BlockTags.getByName(tagKey.getKey()).contains(block);
200+
} else {
201+
isMatch = predicate.getEntities().contains(block.getMapped());
202+
}
271203

272-
return damage;
204+
// If the rule matches the block, check if we still need its properties.
205+
if (isMatch) {
206+
// Check for speed if we haven't found it yet.
207+
if (!speedFound && rule.getSpeed() != null) {
208+
speedMultiplier = rule.getSpeed();
209+
speedFound = true;
210+
}
211+
212+
// Check for drops if we haven't found it yet.
213+
if (!dropsFound && rule.getCorrectForDrops() != null) {
214+
isCorrectToolForDrop = rule.getCorrectForDrops();
215+
dropsFound = true;
216+
}
217+
}
218+
219+
if (speedFound && dropsFound) {
220+
break;
221+
}
222+
}
223+
}
224+
return new ToolSpeedData(speedMultiplier, isCorrectToolForDrop);
225+
}
226+
227+
private static ToolSpeedData getLegacyToolSpeedData(GrimPlayer player, ItemStack tool, StateType block) {
228+
ItemType toolType = tool.getType();
229+
float speedMultiplier = 1.0f;
230+
boolean isCorrectToolForDrop = false;
231+
// 1.13 and below need their own huge methods to support this...
232+
if (toolType.hasAttribute(ItemTypes.ItemAttribute.AXE)) {
233+
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_AXE).contains(block);
234+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.PICKAXE)) {
235+
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_PICKAXE).contains(block);
236+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.SHOVEL)) {
237+
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_SHOVEL).contains(block);
238+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.HOE)) {
239+
isCorrectToolForDrop = player.tagManager.block(SyncedTags.MINEABLE_HOE).contains(block);
240+
}
241+
242+
if (isCorrectToolForDrop) {
243+
int tier = 0;
244+
if (toolType.hasAttribute(ItemTypes.ItemAttribute.WOOD_TIER)) { // Tier 0
245+
speedMultiplier = 2.0f;
246+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.STONE_TIER)) { // Tier 1
247+
speedMultiplier = 4.0f;
248+
tier = 1;
249+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.IRON_TIER)) { // Tier 2
250+
speedMultiplier = 6.0f;
251+
tier = 2;
252+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.DIAMOND_TIER)) { // Tier 3
253+
speedMultiplier = 8.0f;
254+
tier = 3;
255+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.GOLD_TIER)) { // Tier 0
256+
speedMultiplier = 12.0f;
257+
} else if (toolType.hasAttribute(ItemTypes.ItemAttribute.NETHERITE_TIER)) { // Tier 4
258+
speedMultiplier = 9.0f;
259+
tier = 4;
260+
}
261+
262+
if (tier < 3 && player.tagManager.block(SyncedTags.NEEDS_DIAMOND_TOOL).contains(block)) {
263+
isCorrectToolForDrop = false;
264+
} else if (tier < 2 && player.tagManager.block(SyncedTags.NEEDS_IRON_TOOL).contains(block)) {
265+
isCorrectToolForDrop = false;
266+
} else if (tier < 1 && player.tagManager.block(SyncedTags.NEEDS_STONE_TOOL).contains(block)) {
267+
isCorrectToolForDrop = false;
268+
}
269+
}
270+
271+
// Shears can mine some blocks faster
272+
if (toolType == ItemTypes.SHEARS) {
273+
isCorrectToolForDrop = true;
274+
275+
if (block == StateTypes.COBWEB || Materials.isLeaves(block)) {
276+
speedMultiplier = 15.0f;
277+
} else if (BlockTags.WOOL.contains(block)) {
278+
speedMultiplier = 5.0f;
279+
} else if (block == StateTypes.VINE ||
280+
block == StateTypes.GLOW_LICHEN) {
281+
speedMultiplier = 2.0f;
282+
} else {
283+
isCorrectToolForDrop = block == StateTypes.COBWEB ||
284+
block == StateTypes.REDSTONE_WIRE ||
285+
block == StateTypes.TRIPWIRE;
286+
}
287+
}
288+
289+
// Swords can also mine some blocks faster
290+
if (toolType.hasAttribute(ItemTypes.ItemAttribute.SWORD)) {
291+
if (block == StateTypes.COBWEB) {
292+
speedMultiplier = 15.0f;
293+
} else if (player.tagManager.block(SyncedTags.SWORD_EFFICIENT).contains(block)) {
294+
speedMultiplier = 1.5f;
295+
}
296+
297+
isCorrectToolForDrop = block == StateTypes.COBWEB;
298+
}
299+
//
300+
return new ToolSpeedData(speedMultiplier, isCorrectToolForDrop);
273301
}
302+
303+
274304
}

0 commit comments

Comments
 (0)