Skip to content

Commit

Permalink
Account for exterior block hardness in break speed
Browse files Browse the repository at this point in the history
Players were able to cheese hard block collection by surrounding hard
blocks with softer blocks. For example, it was possible to mine up to 8
obsidian at cobblestone break-speed by targeting cobblestone when
breaking. To solve this, a new `AbstractBlockState` mixin was
introduced. I tried to solve this at other levels (preferably without a
mixin), but wasn't able to get all the necessary information anywhere
other than at the BlockState level.

The minimal breaking delta (which is effectively the same as maximum
block hardness) is used instead of the targeted block hardness. Using
the average basically didn't solve the issue—it was possible to surround
a hard block with softer blocks to 'dilute' the hardness.

Fixes Draylar#14

Signed-off-by: Clark Fischer <clark.fischer@gmail.com>
  • Loading branch information
clarkf committed Oct 12, 2023
1 parent be66d62 commit 42bf4eb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
62 changes: 62 additions & 0 deletions src/main/java/dev/draylar/magna/mixin/AbstractBlockStateMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package dev.draylar.magna.mixin;

import dev.draylar.magna.api.MagnaTool;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.List;

/**
* A mixin that calculates the block breaking delta for {@link MagnaTool MagnaTool}s.
*/
@Mixin(AbstractBlock.AbstractBlockState.class)
public class AbstractBlockStateMixin {
/**
* Compute the block breaking delta for {@link MagnaTool}s. If the held item is not a MagnaTool, this mixin
* does nothing.
*
* <p>The delta is computed by taking the minimum delta of the affected blocks. Mining speed is effectively limited
* by the hardest block being broken.
*/
@Inject(
method = "calcBlockBreakingDelta",
at = @At("HEAD"),
cancellable = true
)
public void calcBlockBreakingDelta(PlayerEntity player, BlockView world, BlockPos pos, CallbackInfoReturnable<Float> cir) {
ItemStack stack = player.getInventory().getMainHandStack();
if (stack.getItem() instanceof MagnaTool tool) {
cir.cancel();
int radius = tool.getRadius(stack);
cir.setReturnValue(calculateDelta(tool, player, radius));
}
}

@Unique
private static float calculateDelta(final MagnaTool tool, final PlayerEntity player, final int radius) {
World world = player.getWorld();

// Even though we already have the BlockPosition that the player is targeting, the side information wasn't
// passed along, which is necessary for figuring out how to expand the radius. Just throw that away and
// recompute.
List<BlockPos> blocks = tool.getBlockFinder().findPositions(world, player, radius);

return blocks.stream()
.map(pos -> {
BlockState state = world.getBlockState(pos);
//noinspection deprecation
return state.getBlock().calcBlockBreakingDelta(state, player, world, pos);
})
.min(Float::compare).orElseThrow();
}
}
5 changes: 3 additions & 2 deletions src/main/resources/magna.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
"package": "dev.draylar.magna.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"AbstractBlockStateMixin",
"BlockMixin",
"PlayerInventoryMixin",
"ServerPlayerInteractionManagerMixin",
"WorldMixin"
],
"client": [
"WorldRendererMixin",
"ClientPlayerInteractionManagerMixin"
"ClientPlayerInteractionManagerMixin",
"WorldRendererMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down
13 changes: 13 additions & 0 deletions src/testmod/java/dev/draylar/magna/test/MagnaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dev.draylar.magna.item.ExcavatorItem;
import dev.draylar.magna.item.HammerItem;
import net.fabricmc.api.ModInitializer;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
Expand Down Expand Up @@ -31,6 +32,18 @@ public void onInitialize() {
new HammerItem(ToolMaterials.DIAMOND, 0, 0, new Item.Settings())
);

// Standard hammer with a particularly slow mining speed. Useful for testing break speed.
Registry.register(
Registries.ITEM,
new Identifier("magna", "hammer_slow_test"),
new HammerItem(ToolMaterials.DIAMOND, 0, 0, new Item.Settings()) {
@Override
public float getMiningSpeedMultiplier(ItemStack stack, BlockState state) {
return 1.0f;
}
}
);

// Standard Hammer with a tool material of Diamond and a modified depth.
Registry.register(
Registries.ITEM,
Expand Down

0 comments on commit 42bf4eb

Please sign in to comment.