diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java index 7647b36e6..b9e61a7aa 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java @@ -35,9 +35,9 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; import javax.annotation.Nullable; +import java.util.List; public abstract class AbstractComputerBlock extends HorizontalDirectionalBlock implements IBundledRedstoneBlock, EntityBlock { private static final ResourceLocation DROP = new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer"); @@ -110,9 +110,19 @@ public abstract class AbstractComputerBlock getDrops(BlockState state, LootParams.Builder params) { + if (params.getOptionalParameter(LootContextParams.BLOCK_ENTITY) instanceof AbstractComputerBlockEntity computer) { + params = params.withDynamicDrop(DROP, out -> out.accept(getItem(computer))); + } + + return super.getDrops(state, params); + } + @Override public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity tile, ItemStack tool) { - // Don't drop blocks here - see onBlockHarvested. + // Don't drop blocks here - see playerWillDestroy. player.awardStat(Stats.BLOCK_MINED.get(this)); player.causeFoodExhaustion(0.005F); } @@ -120,25 +130,11 @@ public abstract class AbstractComputerBlock out.accept(getItem(computer))); - for (var item : state.getDrops(context)) { - popResource(world, pos, item); - } - - state.spawnAfterBreak(serverWorld, pos, player.getMainHandItem(), true); - } + dropResources(state, serverLevel, pos, world.getBlockEntity(pos)); } @Override diff --git a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestHelperAccessor.java b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestHelperAccessor.java index 591e35af4..72ebf4e2f 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestHelperAccessor.java +++ b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestHelperAccessor.java @@ -6,16 +6,11 @@ package dan200.computercraft.mixin.gametest; import net.minecraft.gametest.framework.GameTestHelper; import net.minecraft.gametest.framework.GameTestInfo; -import net.minecraft.world.phys.AABB; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(GameTestHelper.class) public interface GameTestHelperAccessor { - @Invoker - AABB callGetBounds(); - @Accessor GameTestInfo getTestInfo(); } diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt index a4ebf599e..0b981cce8 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt @@ -19,9 +19,11 @@ import net.minecraft.gametest.framework.GameTest import net.minecraft.gametest.framework.GameTestHelper import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items +import net.minecraft.world.level.Level import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.LeverBlock import net.minecraft.world.level.block.RedstoneLampBlock +import net.minecraft.world.phys.Vec3 import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.lwjgl.glfw.GLFW @@ -115,6 +117,20 @@ class Computer_Test { thenOnComputer { callPeripheral("right", "size").assertArrayEquals(54) } } + /** + * Tests a computer item is dropped on explosion. + */ + @GameTest + fun Drops_on_explosion(context: GameTestHelper) = context.sequence { + thenExecute { + val pos = BlockPos(2, 2, 2) + val explosionPos = Vec3.atCenterOf(context.absolutePos(pos)) + context.level.explode(null, explosionPos.x, explosionPos.y, explosionPos.z, 2.0f, Level.ExplosionInteraction.TNT) + + context.assertItemEntityPresent(ModRegistry.Items.COMPUTER_NORMAL.get(), pos, 1.0) + } + } + /** * Check the client can open the computer UI and interact with it. */ diff --git a/projects/common/src/testMod/resources/data/cctest/structures/computer_test.drops_on_explosion.snbt b/projects/common/src/testMod/resources/data/cctest/structures/computer_test.drops_on_explosion.snbt new file mode 100644 index 000000000..bc64fcd09 --- /dev/null +++ b/projects/common/src/testMod/resources/data/cctest/structures/computer_test.drops_on_explosion.snbt @@ -0,0 +1,138 @@ +{ + DataVersion: 3465, + size: [5, 5, 5], + data: [ + {pos: [0, 0, 0], state: "minecraft:obsidian"}, + {pos: [0, 0, 1], state: "minecraft:obsidian"}, + {pos: [0, 0, 2], state: "minecraft:obsidian"}, + {pos: [0, 0, 3], state: "minecraft:obsidian"}, + {pos: [0, 0, 4], state: "minecraft:obsidian"}, + {pos: [1, 0, 0], state: "minecraft:obsidian"}, + {pos: [1, 0, 1], state: "minecraft:obsidian"}, + {pos: [1, 0, 2], state: "minecraft:obsidian"}, + {pos: [1, 0, 3], state: "minecraft:obsidian"}, + {pos: [1, 0, 4], state: "minecraft:obsidian"}, + {pos: [2, 0, 0], state: "minecraft:obsidian"}, + {pos: [2, 0, 1], state: "minecraft:obsidian"}, + {pos: [2, 0, 2], state: "minecraft:obsidian"}, + {pos: [2, 0, 3], state: "minecraft:obsidian"}, + {pos: [2, 0, 4], state: "minecraft:obsidian"}, + {pos: [3, 0, 0], state: "minecraft:obsidian"}, + {pos: [3, 0, 1], state: "minecraft:obsidian"}, + {pos: [3, 0, 2], state: "minecraft:obsidian"}, + {pos: [3, 0, 3], state: "minecraft:obsidian"}, + {pos: [3, 0, 4], state: "minecraft:obsidian"}, + {pos: [4, 0, 0], state: "minecraft:obsidian"}, + {pos: [4, 0, 1], state: "minecraft:obsidian"}, + {pos: [4, 0, 2], state: "minecraft:obsidian"}, + {pos: [4, 0, 3], state: "minecraft:obsidian"}, + {pos: [4, 0, 4], state: "minecraft:obsidian"}, + {pos: [0, 1, 0], state: "minecraft:barrier"}, + {pos: [0, 1, 1], state: "minecraft:barrier"}, + {pos: [0, 1, 2], state: "minecraft:barrier"}, + {pos: [0, 1, 3], state: "minecraft:barrier"}, + {pos: [0, 1, 4], state: "minecraft:barrier"}, + {pos: [1, 1, 0], state: "minecraft:barrier"}, + {pos: [1, 1, 1], state: "minecraft:air"}, + {pos: [1, 1, 2], state: "minecraft:air"}, + {pos: [1, 1, 3], state: "minecraft:air"}, + {pos: [1, 1, 4], state: "minecraft:barrier"}, + {pos: [2, 1, 0], state: "minecraft:barrier"}, + {pos: [2, 1, 1], state: "minecraft:air"}, + {pos: [2, 1, 2], state: "computercraft:computer_normal{facing:east,state:off}", nbt: {On: 0b, id: "computercraft:computer_normal"}}, + {pos: [2, 1, 3], state: "minecraft:air"}, + {pos: [2, 1, 4], state: "minecraft:barrier"}, + {pos: [3, 1, 0], state: "minecraft:barrier"}, + {pos: [3, 1, 1], state: "minecraft:air"}, + {pos: [3, 1, 2], state: "minecraft:air"}, + {pos: [3, 1, 3], state: "minecraft:air"}, + {pos: [3, 1, 4], state: "minecraft:barrier"}, + {pos: [4, 1, 0], state: "minecraft:barrier"}, + {pos: [4, 1, 1], state: "minecraft:barrier"}, + {pos: [4, 1, 2], state: "minecraft:barrier"}, + {pos: [4, 1, 3], state: "minecraft:barrier"}, + {pos: [4, 1, 4], state: "minecraft:barrier"}, + {pos: [0, 2, 0], state: "minecraft:barrier"}, + {pos: [0, 2, 1], state: "minecraft:barrier"}, + {pos: [0, 2, 2], state: "minecraft:air"}, + {pos: [0, 2, 3], state: "minecraft:barrier"}, + {pos: [0, 2, 4], state: "minecraft:barrier"}, + {pos: [1, 2, 0], state: "minecraft:barrier"}, + {pos: [1, 2, 1], state: "minecraft:air"}, + {pos: [1, 2, 2], state: "minecraft:air"}, + {pos: [1, 2, 3], state: "minecraft:air"}, + {pos: [1, 2, 4], state: "minecraft:barrier"}, + {pos: [2, 2, 0], state: "minecraft:barrier"}, + {pos: [2, 2, 1], state: "minecraft:air"}, + {pos: [2, 2, 2], state: "minecraft:air"}, + {pos: [2, 2, 3], state: "minecraft:air"}, + {pos: [2, 2, 4], state: "minecraft:barrier"}, + {pos: [3, 2, 0], state: "minecraft:barrier"}, + {pos: [3, 2, 1], state: "minecraft:air"}, + {pos: [3, 2, 2], state: "minecraft:air"}, + {pos: [3, 2, 3], state: "minecraft:air"}, + {pos: [3, 2, 4], state: "minecraft:barrier"}, + {pos: [4, 2, 0], state: "minecraft:barrier"}, + {pos: [4, 2, 1], state: "minecraft:barrier"}, + {pos: [4, 2, 2], state: "minecraft:barrier"}, + {pos: [4, 2, 3], state: "minecraft:barrier"}, + {pos: [4, 2, 4], state: "minecraft:barrier"}, + {pos: [0, 3, 0], state: "minecraft:air"}, + {pos: [0, 3, 1], state: "minecraft:air"}, + {pos: [0, 3, 2], state: "minecraft:air"}, + {pos: [0, 3, 3], state: "minecraft:air"}, + {pos: [0, 3, 4], state: "minecraft:air"}, + {pos: [1, 3, 0], state: "minecraft:air"}, + {pos: [1, 3, 1], state: "minecraft:air"}, + {pos: [1, 3, 2], state: "minecraft:air"}, + {pos: [1, 3, 3], state: "minecraft:air"}, + {pos: [1, 3, 4], state: "minecraft:air"}, + {pos: [2, 3, 0], state: "minecraft:air"}, + {pos: [2, 3, 1], state: "minecraft:air"}, + {pos: [2, 3, 2], state: "minecraft:air"}, + {pos: [2, 3, 3], state: "minecraft:air"}, + {pos: [2, 3, 4], state: "minecraft:air"}, + {pos: [3, 3, 0], state: "minecraft:air"}, + {pos: [3, 3, 1], state: "minecraft:air"}, + {pos: [3, 3, 2], state: "minecraft:air"}, + {pos: [3, 3, 3], state: "minecraft:air"}, + {pos: [3, 3, 4], state: "minecraft:air"}, + {pos: [4, 3, 0], state: "minecraft:air"}, + {pos: [4, 3, 1], state: "minecraft:air"}, + {pos: [4, 3, 2], state: "minecraft:air"}, + {pos: [4, 3, 3], state: "minecraft:air"}, + {pos: [4, 3, 4], state: "minecraft:air"}, + {pos: [0, 4, 0], state: "minecraft:air"}, + {pos: [0, 4, 1], state: "minecraft:air"}, + {pos: [0, 4, 2], state: "minecraft:air"}, + {pos: [0, 4, 3], state: "minecraft:air"}, + {pos: [0, 4, 4], state: "minecraft:air"}, + {pos: [1, 4, 0], state: "minecraft:air"}, + {pos: [1, 4, 1], state: "minecraft:air"}, + {pos: [1, 4, 2], state: "minecraft:air"}, + {pos: [1, 4, 3], state: "minecraft:air"}, + {pos: [1, 4, 4], state: "minecraft:air"}, + {pos: [2, 4, 0], state: "minecraft:air"}, + {pos: [2, 4, 1], state: "minecraft:air"}, + {pos: [2, 4, 2], state: "minecraft:air"}, + {pos: [2, 4, 3], state: "minecraft:air"}, + {pos: [2, 4, 4], state: "minecraft:air"}, + {pos: [3, 4, 0], state: "minecraft:air"}, + {pos: [3, 4, 1], state: "minecraft:air"}, + {pos: [3, 4, 2], state: "minecraft:air"}, + {pos: [3, 4, 3], state: "minecraft:air"}, + {pos: [3, 4, 4], state: "minecraft:air"}, + {pos: [4, 4, 0], state: "minecraft:air"}, + {pos: [4, 4, 1], state: "minecraft:air"}, + {pos: [4, 4, 2], state: "minecraft:air"}, + {pos: [4, 4, 3], state: "minecraft:air"}, + {pos: [4, 4, 4], state: "minecraft:air"} + ], + entities: [], + palette: [ + "minecraft:obsidian", + "minecraft:barrier", + "minecraft:air", + "computercraft:computer_normal{facing:east,state:off}" + ] +}