From 7f2912009b55d1f893c8eecc8361afacc7637323 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 2 Apr 2022 09:47:36 +0200 Subject: [PATCH] Added Block Breaker and Block Placer Machine. Huge thanks to SimonFlapse * Added advancements crafting data for block breaker and placer (From 7a31de7b869e67697f85aeca9f0a5099c6bc7d62) Added Block Breaker Machine (#2871) * Added a new machine that can break blocks in front of it (From e56a51da2b0c4e144cdf70ebff53d7097e81b5ce) Added Block Placer Machine * Added a new machine that can place blocks in front of it (From e80de2ec82e0a14f161137e4b147bb455a839e3d) Added Block Breaker and Placer recipe (From dccdf76eacb8ceb7075897170e098bc346b8b4db) Break blocks instead of removing + Refactoring --- .../blockentity/MachineBaseBlockEntity.java | 3 +- .../blockentity/RedstoneConfigurable.java | 5 + .../java/techreborn/blockentity/GuiType.java | 6 +- .../tier0/block/AbstractBlockBlockEntity.java | 96 ++++++++ .../tier0/block/BlockBreakerBlockEntity.java | 80 +++++++ .../tier0/block/BlockPlacerBlockEntity.java | 80 +++++++ .../machine/tier0/block/BlockProcessable.java | 31 +++ .../machine/tier0/block/BlockProcessor.java | 23 ++ .../tier0/block/BlockProcessorUtils.java | 69 ++++++ .../machine/tier0/block/ProcessingStatus.java | 50 ++++ .../block/blockbreaker/BlockBreakerNbt.java | 61 +++++ .../blockbreaker/BlockBreakerProcessor.java | 224 ++++++++++++++++++ .../blockbreaker/BlockBreakerStatus.java | 60 +++++ .../block/blockplacer/BlockPlacerNbt.java | 61 +++++ .../blockplacer/BlockPlacerProcessor.java | 199 ++++++++++++++++ .../block/blockplacer/BlockPlacerStatus.java | 59 +++++ .../java/techreborn/client/ClientGuiType.java | 5 +- .../client/gui/GuiBlockBreaker.java | 68 ++++++ .../techreborn/client/gui/GuiBlockPlacer.java | 68 ++++++ .../techreborn/config/TechRebornConfig.java | 24 ++ src/main/java/techreborn/init/ModSounds.java | 1 + .../java/techreborn/init/TRBlockEntities.java | 4 + src/main/java/techreborn/init/TRContent.java | 8 +- .../techreborn/blockstates/block_breaker.json | 12 + .../techreborn/blockstates/block_placer.json | 12 + .../assets/techreborn/lang/en_us.json | 26 +- .../tier0_machines/block_breaker.json | 8 + .../machines/tier0_machines/block_placer.json | 8 + .../techreborn/models/item/block_breaker.json | 3 + .../techreborn/models/item/block_placer.json | 3 + .../tier0_machines/block_breaker_front.png | Bin 0 -> 711 bytes .../tier0_machines/block_placer_front.png | Bin 0 -> 689 bytes .../crafting_table/machine/block_breaker.json | 54 +++++ .../crafting_table/machine/block_placer.json | 54 +++++ .../loot_tables/blocks/block_breaker.json | 19 ++ .../loot_tables/blocks/block_placer.json | 19 ++ .../crafting_table/machine/block_breaker.json | 25 ++ .../crafting_table/machine/block_placer.json | 25 ++ 38 files changed, 1543 insertions(+), 10 deletions(-) create mode 100644 RebornCore/src/main/java/reborncore/common/blockentity/RedstoneConfigurable.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/AbstractBlockBlockEntity.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/BlockBreakerBlockEntity.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/BlockPlacerBlockEntity.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessable.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessor.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessorUtils.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/ProcessingStatus.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerNbt.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerProcessor.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerStatus.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerNbt.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerProcessor.java create mode 100644 src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerStatus.java create mode 100644 src/main/java/techreborn/client/gui/GuiBlockBreaker.java create mode 100644 src/main/java/techreborn/client/gui/GuiBlockPlacer.java create mode 100644 src/main/resources/assets/techreborn/blockstates/block_breaker.json create mode 100644 src/main/resources/assets/techreborn/blockstates/block_placer.json create mode 100644 src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_breaker.json create mode 100644 src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_placer.json create mode 100644 src/main/resources/assets/techreborn/models/item/block_breaker.json create mode 100644 src/main/resources/assets/techreborn/models/item/block_placer.json create mode 100644 src/main/resources/assets/techreborn/textures/block/machines/tier0_machines/block_breaker_front.png create mode 100644 src/main/resources/assets/techreborn/textures/block/machines/tier0_machines/block_placer_front.png create mode 100644 src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_breaker.json create mode 100644 src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_placer.json create mode 100644 src/main/resources/data/techreborn/loot_tables/blocks/block_breaker.json create mode 100644 src/main/resources/data/techreborn/loot_tables/blocks/block_placer.json create mode 100644 src/main/resources/data/techreborn/recipes/crafting_table/machine/block_breaker.json create mode 100644 src/main/resources/data/techreborn/recipes/crafting_table/machine/block_placer.json diff --git a/RebornCore/src/main/java/reborncore/common/blockentity/MachineBaseBlockEntity.java b/RebornCore/src/main/java/reborncore/common/blockentity/MachineBaseBlockEntity.java index 72e72f7c5..386947c6f 100644 --- a/RebornCore/src/main/java/reborncore/common/blockentity/MachineBaseBlockEntity.java +++ b/RebornCore/src/main/java/reborncore/common/blockentity/MachineBaseBlockEntity.java @@ -66,7 +66,7 @@ import java.util.Optional; /** * Created by modmuss50 on 04/11/2016. */ -public class MachineBaseBlockEntity extends BlockEntity implements BlockEntityTicker, IUpgradeable, IUpgradeHandler, IListInfoProvider, Inventory, SidedInventory { +public class MachineBaseBlockEntity extends BlockEntity implements BlockEntityTicker, IUpgradeable, IUpgradeHandler, IListInfoProvider, Inventory, SidedInventory, RedstoneConfigurable { public RebornInventory upgradeInventory = new RebornInventory<>(getUpgradeSlotCount(), "upgrades", 1, this, (slotID, stack, face, direction, blockEntity) -> true); private SlotConfiguration slotConfiguration; @@ -518,6 +518,7 @@ public class MachineBaseBlockEntity extends BlockEntity implements BlockEntityTi return redstoneConfiguration; } + @Override public boolean isActive(RedstoneConfiguration.Element element) { return redstoneConfiguration.isActive(element); } diff --git a/RebornCore/src/main/java/reborncore/common/blockentity/RedstoneConfigurable.java b/RebornCore/src/main/java/reborncore/common/blockentity/RedstoneConfigurable.java new file mode 100644 index 000000000..474a16d14 --- /dev/null +++ b/RebornCore/src/main/java/reborncore/common/blockentity/RedstoneConfigurable.java @@ -0,0 +1,5 @@ +package reborncore.common.blockentity; + +public interface RedstoneConfigurable { + boolean isActive(RedstoneConfiguration.Element element); +} diff --git a/src/main/java/techreborn/blockentity/GuiType.java b/src/main/java/techreborn/blockentity/GuiType.java index 3f0b818fa..f681b66dc 100644 --- a/src/main/java/techreborn/blockentity/GuiType.java +++ b/src/main/java/techreborn/blockentity/GuiType.java @@ -40,8 +40,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import reborncore.api.blockentity.IMachineGuiHandler; -import reborncore.common.screen.BuiltScreenHandlerProvider; import reborncore.common.screen.BuiltScreenHandler; +import reborncore.common.screen.BuiltScreenHandlerProvider; import techreborn.blockentity.data.DataDrivenBEProvider; import techreborn.blockentity.generator.PlasmaGeneratorBlockEntity; import techreborn.blockentity.generator.SolarPanelBlockEntity; @@ -54,6 +54,8 @@ import techreborn.blockentity.machine.iron.IronAlloyFurnaceBlockEntity; import techreborn.blockentity.machine.iron.IronFurnaceBlockEntity; import techreborn.blockentity.machine.misc.ChargeOMatBlockEntity; import techreborn.blockentity.machine.multiblock.*; +import techreborn.blockentity.machine.tier0.block.BlockBreakerBlockEntity; +import techreborn.blockentity.machine.tier0.block.BlockPlacerBlockEntity; import techreborn.blockentity.machine.tier1.*; import techreborn.blockentity.machine.tier3.ChunkLoaderBlockEntity; import techreborn.blockentity.machine.tier3.IndustrialCentrifugeBlockEntity; @@ -118,6 +120,8 @@ public final class GuiType implements IMachineGuiHandler public static final GuiType FLUID_REPLICATOR = register("fluid_replicator"); public static final GuiType PLAYER_DETECTOR = register("player_detector"); public static final GuiType DATA_DRIVEN = register("data_driven"); + public static final GuiType BLOCK_BREAKER = register("block_breaker"); + public static final GuiType BLOCK_PLACER = register("block_placer"); private static GuiType register(String id) { return register(new Identifier("techreborn", id)); diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/AbstractBlockBlockEntity.java b/src/main/java/techreborn/blockentity/machine/tier0/block/AbstractBlockBlockEntity.java new file mode 100644 index 000000000..e0add1b15 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/AbstractBlockBlockEntity.java @@ -0,0 +1,96 @@ +package techreborn.blockentity.machine.tier0.block; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import reborncore.client.screen.builder.BlockEntityScreenHandlerBuilder; +import reborncore.client.screen.builder.ScreenHandlerBuilder; +import reborncore.common.blockentity.MachineBaseBlockEntity; +import reborncore.common.recipes.RecipeCrafter; +import reborncore.common.screen.BuiltScreenHandler; +import reborncore.common.screen.BuiltScreenHandlerProvider; +import techreborn.blockentity.machine.GenericMachineBlockEntity; + +public class AbstractBlockBlockEntity extends GenericMachineBlockEntity implements BuiltScreenHandlerProvider, BlockProcessable { + private final int ENERGY_SLOT = 0; + private final int INPUT_SLOT = 1; + + protected BlockProcessor processor; + + /** + * @param blockEntityType + * @param pos + * @param state + * @param name {@link String} Name for a {@link BlockEntity}. + * @param maxInput {@code int} Maximum energy input, value in EU + * @param maxEnergy {@code int} Maximum energy buffer, value in EU + * @param toolDrop {@link Block} Block to drop with wrench + * @param energySlot {@code int} Energy slot to use to charge machine from battery + */ + public AbstractBlockBlockEntity(BlockEntityType blockEntityType, BlockPos pos, BlockState state, String name, int maxInput, int maxEnergy, Block toolDrop, int energySlot) { + super(blockEntityType, pos, state, name, maxInput, maxEnergy, toolDrop, energySlot); + } + + + // BuiltScreenHandlerProvider + @Override + public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) { + BlockEntityScreenHandlerBuilder builder = new ScreenHandlerBuilder("blockplacer") + .player(player.getInventory()) + .inventory() + .hotbar() + .addInventory() + .blockEntity(this) + .energySlot(ENERGY_SLOT, 8 , 72).syncEnergyValue() + .slot(INPUT_SLOT, 80, 60); + + processor.syncNbt(builder); + + return builder.addInventory().create(this, syncID); + } + + @Override + public void tick(World world, BlockPos pos, BlockState state, MachineBaseBlockEntity blockEntity) { + super.tick(world, pos, state, blockEntity); + if (world == null || world.isClient) { + return; + } + + processor.onTick(world, BlockProcessorUtils.getFrontBlockPosition(blockEntity, pos)); + } + + @Override + public void writeNbt(NbtCompound tag) { + super.writeNbt(tag); + processor.writeNbt(tag); + } + + @Override + public void readNbt(NbtCompound tag) { + super.readNbt(tag); + processor.readNbt(tag); + } + + public BlockProcessor getProcessor() { + return processor; + } + + //BlockBreakerProcessable + @Override + public boolean consumeEnergy(int amount) { + return tryUseExact(getEuPerTick(amount)); + } + + //BlockBreakerProcessable + @Override + public void playSound() { + if (RecipeCrafter.soundHandler != null) { + RecipeCrafter.soundHandler.playSound(false, this); + } + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/BlockBreakerBlockEntity.java b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockBreakerBlockEntity.java new file mode 100644 index 000000000..e5a4475fe --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockBreakerBlockEntity.java @@ -0,0 +1,80 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2020 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.blockentity.machine.tier0.block; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; +import reborncore.client.screen.builder.BlockEntityScreenHandlerBuilder; +import reborncore.client.screen.builder.ScreenHandlerBuilder; +import reborncore.common.screen.BuiltScreenHandler; +import reborncore.common.screen.BuiltScreenHandlerProvider; +import reborncore.common.util.RebornInventory; +import techreborn.blockentity.machine.tier0.block.blockbreaker.BlockBreakerProcessor; +import techreborn.config.TechRebornConfig; +import techreborn.init.TRBlockEntities; +import techreborn.init.TRContent; + +/** + * A machine that can break the block physically located in front of it + *
+ * May not break blocks with hardness < 0, may not break blocks that has no item. + * Shares most functionality with other GenericMachineBlockEntities, however does not make use of the {@code RecipeCrafter} + * + * @author SimonFlapse + */ +public class BlockBreakerBlockEntity extends AbstractBlockBlockEntity implements BuiltScreenHandlerProvider, BlockProcessable { + + public static final int ENERGY_SLOT = 0; + public static final int OUTPUT_SLOT = 1; + public static final int FAKE_INPUT_SLOT = 2; + + public BlockBreakerBlockEntity(BlockPos pos, BlockState state) { + super(TRBlockEntities.BLOCK_BREAKER, pos, state, "Block Breaker", TechRebornConfig.blockBreakerMaxInput, TechRebornConfig.blockBreakerMaxEnergy, TRContent.Machine.BLOCK_BREAKER.block, ENERGY_SLOT); + processor = new BlockBreakerProcessor(this, OUTPUT_SLOT, FAKE_INPUT_SLOT, TechRebornConfig.blockBreakerBaseBreakTime, TechRebornConfig.blockBreakerEnergyPerTick); + inventory = new RebornInventory<>(3, "BlockBreakerBlockEntity", 64, this); + } + + // BuiltScreenHandlerProvider + @Override + public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) { + BlockEntityScreenHandlerBuilder builder = new ScreenHandlerBuilder("blockbreaker") + .player(player.getInventory()) + .inventory() + .hotbar() + .addInventory() + .blockEntity(this) + .energySlot(ENERGY_SLOT, 8 , 72).syncEnergyValue() + .outputSlot(OUTPUT_SLOT, 80, 60); + + processor.syncNbt(builder); + + return builder.addInventory().create(this, syncID); + } + + public BlockBreakerProcessor getProcessor() { + return (BlockBreakerProcessor) this.processor; + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/BlockPlacerBlockEntity.java b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockPlacerBlockEntity.java new file mode 100644 index 000000000..9672ba22d --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockPlacerBlockEntity.java @@ -0,0 +1,80 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2020 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.blockentity.machine.tier0.block; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; +import reborncore.client.screen.builder.BlockEntityScreenHandlerBuilder; +import reborncore.client.screen.builder.ScreenHandlerBuilder; +import reborncore.common.screen.BuiltScreenHandler; +import reborncore.common.screen.BuiltScreenHandlerProvider; +import reborncore.common.util.RebornInventory; +import techreborn.blockentity.machine.tier0.block.blockplacer.BlockPlacerProcessor; +import techreborn.config.TechRebornConfig; +import techreborn.init.TRBlockEntities; +import techreborn.init.TRContent; + +/** + * A machine that can break place blocks in front of it + *
+ * May not place blocks with hardness < 0. + * Shares most functionality with other GenericMachineBlockEntities, however does not make use of the {@code RecipeCrafter} + * + * @author SimonFlapse + */ +public class BlockPlacerBlockEntity extends AbstractBlockBlockEntity implements BuiltScreenHandlerProvider, BlockProcessable { + + public static final int ENERGY_SLOT = 0; + public static final int INPUT_SLOT = 1; + public static final int FAKE_OUTPUT_SLOT = 2; + + public BlockPlacerBlockEntity(BlockPos pos, BlockState state) { + super(TRBlockEntities.BLOCK_PLACER, pos, state, "Block Placer", TechRebornConfig.blockPlacerMaxInput, TechRebornConfig.blockPlacerMaxEnergy, TRContent.Machine.BLOCK_PLACER.block, ENERGY_SLOT); + processor = new BlockPlacerProcessor(this, INPUT_SLOT, FAKE_OUTPUT_SLOT, TechRebornConfig.blockPlacerBaseBreakTime, TechRebornConfig.blockPlacerEnergyPerTick); + inventory = new RebornInventory<>(3, "BlockPlacerBlockEntity", 64, this); + } + + // BuiltScreenHandlerProvider + @Override + public BuiltScreenHandler createScreenHandler(int syncID, PlayerEntity player) { + BlockEntityScreenHandlerBuilder builder = new ScreenHandlerBuilder("blockplacer") + .player(player.getInventory()) + .inventory() + .hotbar() + .addInventory() + .blockEntity(this) + .energySlot(ENERGY_SLOT, 8 , 72).syncEnergyValue() + .slot(INPUT_SLOT, 80, 60); + + processor.syncNbt(builder); + + return builder.addInventory().create(this, syncID); + } + + public BlockPlacerProcessor getProcessor() { + return (BlockPlacerProcessor) this.processor; + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessable.java b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessable.java new file mode 100644 index 000000000..9a7f3a7d5 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessable.java @@ -0,0 +1,31 @@ +package techreborn.blockentity.machine.tier0.block; + +import reborncore.api.blockentity.InventoryProvider; +import reborncore.common.blockentity.RedstoneConfigurable; +import reborncore.common.recipes.IUpgradeHandler; + +/** + * Aggregated interface for use with BlockEntities that have a processor attached + *
+ * Example of a processor {@link techreborn.blockentity.machine.tier0.block.blockplacer.BlockPlacerProcessor} + * + * @author SimonFlapse + */ +public interface BlockProcessable extends IUpgradeHandler, RedstoneConfigurable, InventoryProvider { + /** + * Consume some amount of Energy + *
+ * Must only return true if it successfully consumed energy. + * Must not consume energy if only partial fulfilled + * + * @param amount {@code int} amount of energy to consume + * @return if the energy could be consumed + */ + boolean consumeEnergy(int amount); + + + /** + * Play a sound to the Minecraft world + */ + void playSound(); +} \ No newline at end of file diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessor.java b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessor.java new file mode 100644 index 000000000..71a123d7e --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessor.java @@ -0,0 +1,23 @@ +package techreborn.blockentity.machine.tier0.block; + +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import reborncore.client.screen.builder.BlockEntityScreenHandlerBuilder; + +public interface BlockProcessor { + + ProcessingStatus onTick(World world, BlockPos positionInFront); + ProcessingStatus getStatusEnum(); + + int getCurrentTickTime(); + int getTickTime(); + + void readNbt(NbtCompound tag); + void writeNbt(NbtCompound tag); + BlockEntityScreenHandlerBuilder syncNbt(BlockEntityScreenHandlerBuilder builder); + + default int getProgress() { + return (int) (((double) getCurrentTickTime() / (double) getTickTime()) * 100); + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessorUtils.java b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessorUtils.java new file mode 100644 index 000000000..b3a6a07d1 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/BlockProcessorUtils.java @@ -0,0 +1,69 @@ +package techreborn.blockentity.machine.tier0.block; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import reborncore.common.blockentity.MachineBaseBlockEntity; + +/** + * Common utilities for BlockProcessors + *
+ * Only exposes static methods + * + * @author SimonFlapse + */ +public class BlockProcessorUtils { + private BlockProcessorUtils() {}; + + /** + * Get the hardness to break of a block + * @param world {@link World} the world where the blockInFront is in + * @param blockInFront {@link BlockState} the block from which to get the hardness + * @param positionInFront {@link BlockPos} the position of the block from which to get the hardness + * @return the hardness to break of the supplied {@link BlockState} + */ + public static float getHardness(World world, BlockState blockInFront, BlockPos positionInFront) { + float hardness = blockInFront.getHardness(world, positionInFront); + return hardness; + } + + + /** + * Get processing time adjusted to the hardness of a block and the overclocking speed + *
+ * Minimum value is 1 tick + * @param processable {@link BlockProcessable} the machine from which to get the speed multiplier of + * @param baseTickTime {@code int} the base processing time in ticks + * @param hardness {@code float} the hardness of the processed block + * @return time to process a block in ticks given the hardness, speed multiplier and base processing time + */ + public static int getProcessTimeWithHardness(BlockProcessable processable, int baseTickTime, float hardness) { + int placeTime = (int) (baseTickTime * hardness * (1.0 - processable.getSpeedMultiplier())); + return Math.max(placeTime, 1); + } + + /** + * Play a sound in a regular interval of 20 ticks + *
+ * Prevents spamming a new sound every tick, instead only allowing for a sound to be played every 20 tick. + * @param processable {@link BlockProcessable} the machine which should play the sound + * @param currentTick {@code int} the current tick of the processing + */ + public static void playSound(BlockProcessable processable, int currentTick) { + if (currentTick == 1 || currentTick % 20 == 0) { + processable.playSound(); + } + } + + /** + * Get the position of the block in front of the blockEntity + *
+ * @param blockEntity + * @param pos + * @return + */ + public static BlockPos getFrontBlockPosition(MachineBaseBlockEntity blockEntity, BlockPos pos) { + return pos.offset(blockEntity.getFacing() == null? Direction.NORTH : blockEntity.getFacing()); + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/ProcessingStatus.java b/src/main/java/techreborn/blockentity/machine/tier0/block/ProcessingStatus.java new file mode 100644 index 000000000..c86b067b5 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/ProcessingStatus.java @@ -0,0 +1,50 @@ +package techreborn.blockentity.machine.tier0.block; + +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; + +/** + * Interface describing different statuses of a Processing Machine + *
+ * Used to define {@link TranslatableText} for UI elements based on the positive, neutral or negative status of a machine + * + * @author SimonFlapse + */ +public interface ProcessingStatus { + /** + * The status state described as a translatable text + * + * @return The translatable text for displaying in a UI + */ + Text getText(); + + /** + * The processing status with current progress formatted + *
+ * May not always use the passed progress value + * + * @param progress {@code int} the current progress as an integer between 0 and 100. Displayed as a percentage (Eg. 75%) + * @return The translatable text for displaying in a UI + */ + Text getProgressText(int progress); + + /** + * The color to be used for the status text + *
+ * Used to help describe the implication of a status effect + * e.g red for critical status, blue for informational status or green for positive status + * + * @return the color represented as an integer + */ + int getColor(); + + /** + * Integer representation of a status + *
+ * Similar to, or fully based on {@link Enum#ordinal()} + * + * @return an integer corresponding to the status code + * @see Enum#ordinal() + */ + int getStatusCode(); +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerNbt.java b/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerNbt.java new file mode 100644 index 000000000..82b4ceca3 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerNbt.java @@ -0,0 +1,61 @@ +package techreborn.blockentity.machine.tier0.block.blockbreaker; + +import net.minecraft.nbt.NbtCompound; +import reborncore.client.screen.builder.BlockEntityScreenHandlerBuilder; +import techreborn.blockentity.machine.tier0.block.ProcessingStatus; + +/** + * Class handling Nbt values of the Block Breaker + *
+ * Inherited by the {@link BlockBreakerProcessor} for keeping its values in sync when saving/loading a map + * + * @author SimonFlapse + * @see BlockBreakerProcessor + */ +class BlockBreakerNbt { + protected int breakTime; + protected int currentBreakTime; + protected ProcessingStatus status = BlockBreakerStatus.IDLE; + + public void writeNbt(NbtCompound tag) { + tag.putInt("breakTime", this.breakTime); + tag.putInt("currentBreakTime", this.currentBreakTime); + tag.putInt("blockBreakerStatus", getStatus()); + } + + public void readNbt(NbtCompound tag) { + this.breakTime = tag.getInt("breakTime"); + this.currentBreakTime = tag.getInt("currentBreakTime"); + setStatus(tag.getInt("blockBreakerStatus")); + } + + public BlockEntityScreenHandlerBuilder syncNbt(BlockEntityScreenHandlerBuilder builder) { + return builder.sync(this::getBreakTime, this::setBreakTime) + .sync(this::getCurrentBreakTime, this::setCurrentBreakTime) + .sync(this::getStatus, this::setStatus); + } + + protected int getBreakTime() { + return breakTime; + } + + protected void setBreakTime(int breakTime) { + this.breakTime = breakTime; + } + + protected int getCurrentBreakTime() { + return currentBreakTime; + } + + protected void setCurrentBreakTime(int currentBreakTime) { + this.currentBreakTime = currentBreakTime; + } + + protected int getStatus() { + return status.getStatusCode(); + } + + protected void setStatus(int status) { + this.status = BlockBreakerStatus.values()[status]; + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerProcessor.java b/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerProcessor.java new file mode 100644 index 000000000..28830306c --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerProcessor.java @@ -0,0 +1,224 @@ +package techreborn.blockentity.machine.tier0.block.blockbreaker; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import reborncore.common.blockentity.RedstoneConfiguration; +import techreborn.blockentity.machine.tier0.block.BlockProcessable; +import techreborn.blockentity.machine.tier0.block.BlockProcessor; +import techreborn.blockentity.machine.tier0.block.BlockProcessorUtils; +import techreborn.blockentity.machine.tier0.block.ProcessingStatus; + +import java.util.UUID; + +/** + * Class handling the process of breaking a block + *
+ * The main purpose of this class is to implement the {@link #onTick(World, BlockPos)}. + * This method defines the logic for breaking a block + * + * @author SimonFlapse + * @see techreborn.blockentity.machine.tier0.block.BlockBreakerBlockEntity + */ +public class BlockBreakerProcessor extends BlockBreakerNbt implements BlockProcessor { + + private UUID processorId = UUID.randomUUID(); + private BlockProcessable processable; + + private int outputSlot; + private int fakeInputSlot; + + private int baseBreakTime; + private int baseCostToBreak; + + public BlockBreakerProcessor(BlockProcessable processable, int outputSlot, int fakeInputSlot, int baseBreakTime, int baseCostToBreak) { + this.processable = processable; + + this.outputSlot = outputSlot; + this.fakeInputSlot = fakeInputSlot; + + this.baseBreakTime = baseBreakTime; + this.baseCostToBreak = baseCostToBreak; + } + + @Override + public ProcessingStatus getStatusEnum() { + return status; + } + + public ProcessingStatus onTick(World world, BlockPos positionInFront) { + handleBlockBreakingProgressReset(world, positionInFront); + + if (!ensureRedstoneEnabled()) return status; + + if (!handleInterrupted()) return status; + + ItemStack outputItemStack = processable.getInventory().getStack(outputSlot); + + BlockState blockInFront = world.getBlockState(positionInFront); + + if (!handleBlockInFrontRemoved(blockInFront)) return status; + + Item currentBreakingItem = processable.getInventory().getStack(fakeInputSlot).getItem(); + + ItemStack item = blockInFront.getBlock().asItem().getDefaultStack().copy(); + + ItemStack fakeItem = item.copy(); + + if (fakeItem.isOf(Items.AIR)) { + currentBreakingItem = null; + } + + processable.getInventory().setStack(fakeInputSlot, fakeItem); + + float hardness = BlockProcessorUtils.getHardness(world, blockInFront, positionInFront); + + if (!ensureBlockCanBeBroken(blockInFront, fakeItem, hardness)) return status; + + this.breakTime = BlockProcessorUtils.getProcessTimeWithHardness(processable, baseBreakTime, hardness); + + if (!ensureBlockNotReplaced(currentBreakingItem, item)) return status; + + if (!ensureBlockFitInOutput(outputItemStack, item)) return status; + + if (!increaseBreakTime(world, positionInFront)) return status; + + BlockProcessorUtils.playSound(processable, currentBreakTime); + + breakBlock(world, positionInFront, outputItemStack, item); + + status = BlockBreakerStatus.PROCESSING; + + return status; + } + + private boolean ensureRedstoneEnabled() { + if (!processable.isActive(RedstoneConfiguration.RECIPE_PROCESSING)) { + return breakControlFlow(BlockBreakerStatus.IDLE_PAUSED); + } + + return true; + } + + private void handleBlockBreakingProgressReset(World world, BlockPos pos) { + //Resets the BlockBreakingProgress, otherwise the progress will be buggy when a new block has been placed + if (currentBreakTime == 0) { + setBlockBreakingProgress(world, pos, -1); + } + } + + private boolean handleInterrupted() { + //Persists the last status message until the currentBreakTime is back to 0 + //Set the currentBreakTime to less than 0 for as many ticks as you want a message to persist. + //The machine processing is halted while persisting messages. + if (currentBreakTime < 0) { + this.currentBreakTime++; + return false; + } + return true; + } + + private boolean handleBlockInFrontRemoved(BlockState blockInFront) { + //Makes sure that if the block in front is removed, the processing resets + if (blockInFront.isOf(Blocks.AIR)) { + processable.getInventory().setStack(fakeInputSlot, ItemStack.EMPTY); + resetProcessing(0); + } + + return true; + } + + private boolean ensureBlockCanBeBroken(BlockState blockInFront, ItemStack fakeItem, float hardness) { + //Resets time if there is no block + //If breaking the block returns no output, skip breaking it + //Blocks with a hardness below 0 are unbreakable + if (blockInFront.isAir() || fakeItem.isEmpty() || hardness < 0) { + return breakControlFlow(BlockBreakerStatus.IDLE); + } + + return true; + } + + private boolean ensureBlockNotReplaced(Item currentBreakingItem, ItemStack item) { + //Ensures that a piston cannot be abused to push in another block without resetting the progress + if (currentBreakingItem != null && !ItemStack.EMPTY.isOf(currentBreakingItem) && !item.isOf(currentBreakingItem)) { + return breakControlFlow(BlockBreakerStatus.INTERRUPTED); + } + + return true; + } + + private boolean ensureBlockFitInOutput(ItemStack currentStack, ItemStack item) { + //Ensures that the block is the same as the one currently in the output slot + if (!currentStack.isOf(ItemStack.EMPTY.getItem()) && !currentStack.isOf(item.getItem())) { + return breakControlFlow(BlockBreakerStatus.OUTPUT_BLOCKED); + } + + //Ensure that output slot can fit the block + if (currentStack.getMaxCount() < currentStack.getCount() + item.getCount()) { + return breakControlFlow(BlockBreakerStatus.OUTPUT_FULL); + } + + return true; + } + + private boolean increaseBreakTime(World world, BlockPos blockPos) { + //if (!tryUseExact(getEuPerTick(baseCostToBreak))) { + if (!processable.consumeEnergy(baseCostToBreak)) { + return breakControlFlow(BlockBreakerStatus.NO_ENERGY); + } + + setBlockBreakingProgress(world, blockPos); + this.currentBreakTime++; + return true; + } + + private void breakBlock(World world, BlockPos positionInFront, ItemStack currentStack, ItemStack item) { + if (currentBreakTime >= breakTime) { + + world.breakBlock(positionInFront, false); + + resetProcessing(0); + + if (currentStack.isOf(ItemStack.EMPTY.getItem())) { + processable.getInventory().setStack(outputSlot, item); + } else { + int currentCount = currentStack.getCount(); + currentStack.setCount(currentCount + item.getCount()); + } + } + } + + private void resetProcessing(int tick) { + this.currentBreakTime = tick; + breakTime = baseBreakTime; + } + + private void setBlockBreakingProgress(World world, BlockPos blockPos) { + setBlockBreakingProgress(world, blockPos, getProgress() / 10); + } + + private void setBlockBreakingProgress(World world, BlockPos blockPos, int breakingProgress) { + world.setBlockBreakingInfo(processorId.hashCode(), blockPos, breakingProgress); + } + + @Override + public int getCurrentTickTime() { + return this.getCurrentBreakTime(); + } + + @Override + public int getTickTime() { + return this.getBreakTime(); + } + + private boolean breakControlFlow(ProcessingStatus status) { + resetProcessing(-20); + this.status = status; + return false; + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerStatus.java b/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerStatus.java new file mode 100644 index 000000000..34c3e4942 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/blockbreaker/BlockBreakerStatus.java @@ -0,0 +1,60 @@ +package techreborn.blockentity.machine.tier0.block.blockbreaker; + +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import reborncore.common.util.Color; +import techreborn.blockentity.machine.tier0.block.ProcessingStatus; + +/** + * An enumeration of different statuses the Block Breaker can have + * + * Includes {@code TranslatableText} describing the status along with a text color + * + * @author SimonFlapse + */ +enum BlockBreakerStatus implements ProcessingStatus { + IDLE(new TranslatableText("gui.techreborn.block_breaker.idle"), Color.BLUE), + IDLE_PAUSED(new TranslatableText("gui.techreborn.block.idle_redstone"), Color.BLUE), + OUTPUT_FULL(new TranslatableText("gui.techreborn.block.output_full"), Color.RED), + NO_ENERGY(new TranslatableText("gui.techreborn.block.no_energy"), Color.RED), + INTERRUPTED(new TranslatableText("gui.techreborn.block.interrupted"), Color.RED), + OUTPUT_BLOCKED(new TranslatableText("gui.techreborn.block.output_blocked"), Color.RED), + PROCESSING(new TranslatableText("gui.techreborn.block_breaker.processing"), Color.GREEN); + + private final Text text; + private final int color; + + BlockBreakerStatus(Text text, Color color) { + this.text = text; + this.color = color.getColor(); + } + + @Override + public Text getText() { + return text; + } + + @Override + public Text getProgressText(int progress) { + progress = Math.max(progress, 0); + + if (this == PROCESSING) { + return new TranslatableText("gui.techreborn.block.progress.active", new LiteralText("" + progress + "%")); + } else if (this == IDLE || this == INTERRUPTED) { + return new TranslatableText("gui.techreborn.block.progress.stopped"); + } + + return new TranslatableText("gui.techreborn.block.progress.paused", new LiteralText("" + progress + "%")); + } + + @Override + public int getColor() { + return color; + } + + @Override + public int getStatusCode() { + return this.ordinal(); + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerNbt.java b/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerNbt.java new file mode 100644 index 000000000..98a116f02 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerNbt.java @@ -0,0 +1,61 @@ +package techreborn.blockentity.machine.tier0.block.blockplacer; + +import net.minecraft.nbt.NbtCompound; +import reborncore.client.screen.builder.BlockEntityScreenHandlerBuilder; +import techreborn.blockentity.machine.tier0.block.ProcessingStatus; + +/** + * Class handling Nbt values of the Block Placer + *
+ * Inherited by the {@link BlockPlacerProcessor} for keeping its values in sync when saving/loading a map + * + * @author SimonFlapse + * @see BlockPlacerProcessor + */ +class BlockPlacerNbt { + protected int placeTime; + protected int currentPlaceTime; + protected ProcessingStatus status = BlockPlacerStatus.IDLE; + + public void writeNbt(NbtCompound tag) { + tag.putInt("placeTime", this.placeTime); + tag.putInt("currentPlaceTime", this.currentPlaceTime); + tag.putInt("blockPlacerStatus", getStatus()); + } + + public void readNbt(NbtCompound tag) { + this.placeTime = tag.getInt("placeTime"); + this.currentPlaceTime = tag.getInt("currentPlaceTime"); + setStatus(tag.getInt("blockPlacerStatus")); + } + + public BlockEntityScreenHandlerBuilder syncNbt(BlockEntityScreenHandlerBuilder builder) { + return builder.sync(this::getPlaceTime, this::setPlaceTime) + .sync(this::getCurrentPlaceTime, this::setCurrentPlaceTime) + .sync(this::getStatus, this::setStatus); + } + + protected int getPlaceTime() { + return placeTime; + } + + protected void setPlaceTime(int placeTime) { + this.placeTime = placeTime; + } + + protected int getCurrentPlaceTime() { + return currentPlaceTime; + } + + protected void setCurrentPlaceTime(int currentPlaceTime) { + this.currentPlaceTime = currentPlaceTime; + } + + protected int getStatus() { + return status.getStatusCode(); + } + + protected void setStatus(int status) { + this.status = BlockPlacerStatus.values()[status]; + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerProcessor.java b/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerProcessor.java new file mode 100644 index 000000000..c3e13df08 --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerProcessor.java @@ -0,0 +1,199 @@ +package techreborn.blockentity.machine.tier0.block.blockplacer; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import reborncore.common.blockentity.RedstoneConfiguration; +import techreborn.blockentity.machine.tier0.block.BlockProcessable; +import techreborn.blockentity.machine.tier0.block.BlockProcessor; +import techreborn.blockentity.machine.tier0.block.BlockProcessorUtils; +import techreborn.blockentity.machine.tier0.block.ProcessingStatus; + +/** + * Class handling the process of placing a block + *
+ * The main purpose of this class is to implement the {@link #onTick(World, BlockPos)}. + * This method defines the logic for placing a block + * + * @author SimonFlapse + * @see techreborn.blockentity.machine.tier0.block.BlockPlacerBlockEntity + */ +public class BlockPlacerProcessor extends BlockPlacerNbt implements BlockProcessor { + + private BlockProcessable processable; + + private int inputSlot; + private int fakeOutputSlot; + + private int basePlaceTime; + private int baseCostToPlace; + + public BlockPlacerProcessor(BlockProcessable processable, int inputSlot, int fakeOutputSlot, int basePlaceTime, int baseCostToPlace) { + this.processable = processable; + + this.inputSlot = inputSlot; + this.fakeOutputSlot = fakeOutputSlot; + + this.basePlaceTime = basePlaceTime; + this.baseCostToPlace = baseCostToPlace; + } + + public ProcessingStatus getStatusEnum() { + return status; + } + + @Override + public int getCurrentTickTime() { + return getCurrentPlaceTime(); + } + + @Override + public int getTickTime() { + return getPlaceTime(); + } + + public ProcessingStatus onTick(World world, BlockPos positionInFront) { + if (!ensureRedstoneEnabled()) return status; + + if (!handleInterrupted()) return status; + + ItemStack inputItemStack = processable.getInventory().getStack(inputSlot); + + if (!handleInputSlotEmptied(inputItemStack)) return status; + + BlockState blockInFront = world.getBlockState(positionInFront); + + if (!ensureEnoughItemsToPlace(inputItemStack)) return status; + + if (!ensureBlockCanBePlaced(blockInFront, inputItemStack, 1)) return status; + + Item currentPlacingItem = processable.getInventory().getStack(fakeOutputSlot).getItem(); + + ItemStack fakeItem = inputItemStack.copy(); + + if (fakeItem.isOf(Items.AIR)) { + currentPlacingItem = null; + } + + processable.getInventory().setStack(fakeOutputSlot, fakeItem); + + BlockState resultingBlockState = Block.getBlockFromItem(inputItemStack.getItem()).getDefaultState(); + + float hardness = BlockProcessorUtils.getHardness(world, resultingBlockState, positionInFront); + + this.placeTime = BlockProcessorUtils.getProcessTimeWithHardness(processable, basePlaceTime, hardness); + + if (!ensureItemNotReplaced(currentPlacingItem, inputItemStack)) return status; + + if (!increasePlaceTime()) return status; + + BlockProcessorUtils.playSound(processable, currentPlaceTime); + + placeBlock(world, positionInFront, inputItemStack); + + status = BlockPlacerStatus.PROCESSING; + + return status; + } + + private boolean ensureRedstoneEnabled() { + if (!processable.isActive(RedstoneConfiguration.RECIPE_PROCESSING)) { + return breakControlFlow(BlockPlacerStatus.IDLE_PAUSED); + } + + return true; + } + + private boolean handleInterrupted() { + //Persists the last status message until the currentPlaceTime is back to 0 + //Set the currentPlaceTime to less than 0 for as many ticks as you want a message to persist. + //The machine processing is halted while persisting messages. + if (currentPlaceTime < 0) { + this.currentPlaceTime++; + return false; + } + + return true; + } + + private boolean handleInputSlotEmptied(ItemStack inputStack) { + //Makes sure that if the input slot is emptied, the processing resets + if (inputStack.isOf(ItemStack.EMPTY.getItem())) { + processable.getInventory().setStack(fakeOutputSlot, ItemStack.EMPTY); + resetProcessing(0); + } + + return true; + } + + private boolean ensureEnoughItemsToPlace(ItemStack currentStack) { + //Ensure that we have enough items in the input to place + if (currentStack.getCount() <= 0) { + return breakControlFlow(BlockPlacerStatus.IDLE); + } + + return true; + } + + private boolean ensureBlockCanBePlaced(BlockState blockInFront, ItemStack fakeItem, float hardness) { + //Checks if the block can be placed + //Items for which the default BlockState is an air block should not be placed, that will just destroy the item + //Blocks with hardness below 0 can not be broken, and thus should not be placed + BlockState blockState = Block.getBlockFromItem(fakeItem.getItem()).getDefaultState(); + if (blockState.isAir() || hardness < 0) { + return breakControlFlow(BlockPlacerStatus.IDLE); + } + + //Checks if output is blocked + if (!blockInFront.isAir()) { + return breakControlFlow(BlockPlacerStatus.OUTPUT_BLOCKED); + } + + return true; + } + + private boolean ensureItemNotReplaced(Item currentPlacingItem, ItemStack item) { + //Ensures that a smart replace of item, will cause the processing to restart + if (currentPlacingItem != null && !ItemStack.EMPTY.isOf(currentPlacingItem) && !item.isOf(currentPlacingItem)) { + return breakControlFlow(BlockPlacerStatus.INTERRUPTED); + } + + return true; + } + + private boolean increasePlaceTime() { + if (!processable.consumeEnergy(baseCostToPlace)) { + return breakControlFlow(BlockPlacerStatus.NO_ENERGY); + } + this.currentPlaceTime++; + + return true; + } + + private void placeBlock(World world, BlockPos positionInFront, ItemStack currentStack) { + if (currentPlaceTime >= placeTime) { + ItemStack itemStack = processable.getInventory().getStack(inputSlot); + + world.setBlockState(positionInFront, Block.getBlockFromItem(currentStack.getItem()).getDefaultState()); + itemStack.setCount(itemStack.getCount() - 1); + + resetProcessing(0); + } + } + + private void resetProcessing(int tick) { + this.currentPlaceTime = tick; + this.placeTime = basePlaceTime; + this.processable.getInventory().setStack(fakeOutputSlot, ItemStack.EMPTY); + } + + private boolean breakControlFlow(ProcessingStatus status) { + resetProcessing(-20); + this.status = status; + return false; + } +} diff --git a/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerStatus.java b/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerStatus.java new file mode 100644 index 000000000..86db76f6b --- /dev/null +++ b/src/main/java/techreborn/blockentity/machine/tier0/block/blockplacer/BlockPlacerStatus.java @@ -0,0 +1,59 @@ +package techreborn.blockentity.machine.tier0.block.blockplacer; + +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import reborncore.common.util.Color; +import techreborn.blockentity.machine.tier0.block.ProcessingStatus; + +/** + * An enumeration of different statuses the Block Placer can have + * + * Includes {@code TranslatableText} describing the status along with a text color + * + * @author SimonFlapse + */ +enum BlockPlacerStatus implements ProcessingStatus { + IDLE(new TranslatableText("gui.techreborn.block_placer.idle"), Color.BLUE), + IDLE_PAUSED(new TranslatableText("gui.techreborn.block.idle_redstone"), Color.BLUE), + NO_ENERGY(new TranslatableText("gui.techreborn.block.no_energy"), Color.RED), + INTERRUPTED(new TranslatableText("gui.techreborn.block.interrupted"), Color.RED), + OUTPUT_BLOCKED(new TranslatableText("gui.techreborn.block.output_blocked"), Color.RED), + PROCESSING(new TranslatableText("gui.techreborn.block_placer.processing"), Color.GREEN); + + private final Text text; + private final int color; + + BlockPlacerStatus(Text text, Color color) { + this.text = text; + this.color = color.getColor(); + } + + @Override + public Text getText() { + return text; + } + + @Override + public Text getProgressText(int progress) { + progress = Math.max(progress, 0); + + if (this == PROCESSING) { + return new TranslatableText("gui.techreborn.block.progress.active", new LiteralText("" + progress + "%")); + } else if (this == IDLE || this == INTERRUPTED) { + return new TranslatableText("gui.techreborn.block.progress.stopped"); + } else { + return new TranslatableText("gui.techreborn.block.progress.paused", new LiteralText("" + progress + "%")); + } + } + + @Override + public int getColor() { + return color; + } + + @Override + public int getStatusCode() { + return this.ordinal(); + } +} diff --git a/src/main/java/techreborn/client/ClientGuiType.java b/src/main/java/techreborn/client/ClientGuiType.java index ae26d0a28..11eab3565 100644 --- a/src/main/java/techreborn/client/ClientGuiType.java +++ b/src/main/java/techreborn/client/ClientGuiType.java @@ -31,7 +31,6 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.Identifier; import techreborn.blockentity.GuiType; import techreborn.blockentity.data.DataDrivenBEProvider; -import techreborn.client.gui.DataDrivenGui; import techreborn.blockentity.generator.PlasmaGeneratorBlockEntity; import techreborn.blockentity.generator.SolarPanelBlockEntity; import techreborn.blockentity.generator.advanced.DieselGeneratorBlockEntity; @@ -43,6 +42,8 @@ import techreborn.blockentity.machine.iron.IronAlloyFurnaceBlockEntity; import techreborn.blockentity.machine.iron.IronFurnaceBlockEntity; import techreborn.blockentity.machine.misc.ChargeOMatBlockEntity; import techreborn.blockentity.machine.multiblock.*; +import techreborn.blockentity.machine.tier0.block.BlockBreakerBlockEntity; +import techreborn.blockentity.machine.tier0.block.BlockPlacerBlockEntity; import techreborn.blockentity.machine.tier1.*; import techreborn.blockentity.machine.tier3.ChunkLoaderBlockEntity; import techreborn.blockentity.machine.tier3.IndustrialCentrifugeBlockEntity; @@ -110,6 +111,8 @@ public class ClientGuiType { public static final ClientGuiType FLUID_REPLICATOR = register(GuiType.FLUID_REPLICATOR, GuiFluidReplicator::new); public static final ClientGuiType PLAYER_DETECTOR = register(GuiType.PLAYER_DETECTOR, GuiPlayerDetector::new); public static final ClientGuiType DATA_DRIVEN = register(GuiType.DATA_DRIVEN, DataDrivenGui::new); + public static final ClientGuiType BLOCK_BREAKER = register(GuiType.BLOCK_BREAKER, GuiBlockBreaker::new); + public static final ClientGuiType BLOCK_PLACER = register(GuiType.BLOCK_PLACER, GuiBlockPlacer::new); private static ClientGuiType register(GuiType type, GuiFactory factory) { return new ClientGuiType<>(type, factory); diff --git a/src/main/java/techreborn/client/gui/GuiBlockBreaker.java b/src/main/java/techreborn/client/gui/GuiBlockBreaker.java new file mode 100644 index 000000000..334215eaa --- /dev/null +++ b/src/main/java/techreborn/client/gui/GuiBlockBreaker.java @@ -0,0 +1,68 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2020 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.client.gui; + +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerEntity; +import reborncore.client.gui.builder.GuiBase; +import reborncore.common.screen.BuiltScreenHandler; +import techreborn.blockentity.machine.tier0.block.BlockBreakerBlockEntity; +import techreborn.blockentity.machine.tier0.block.blockbreaker.BlockBreakerProcessor; + +public class GuiBlockBreaker extends GuiBase { + + BlockBreakerBlockEntity blockEntity; + + public GuiBlockBreaker(int syncID, final PlayerEntity player, final BlockBreakerBlockEntity blockEntity) { + super(player, blockEntity, blockEntity.createScreenHandler(syncID, player)); + this.blockEntity = blockEntity; + } + + @Override + protected void drawBackground(MatrixStack matrixStack, final float f, final int mouseX, final int mouseY) { + super.drawBackground(matrixStack, f, mouseX, mouseY); + final Layer layer = Layer.BACKGROUND; + + BlockBreakerProcessor processor = blockEntity.getProcessor(); + + drawSlot(matrixStack, 8, 72, layer); + + drawCentredText(matrixStack, blockEntity.getProcessor().getStatusEnum().getText(), 25, processor.getStatusEnum().getColor(), layer); + + drawCentredText(matrixStack, processor.getStatusEnum().getProgressText(processor.getProgress()), 40, processor.getStatusEnum().getColor(), layer); + + drawOutputSlot(matrixStack, 80, 60, layer); + + builder.drawJEIButton(matrixStack, this, 158, 5, layer); + } + + @Override + protected void drawForeground(MatrixStack matrixStack, final int mouseX, final int mouseY) { + super.drawForeground(matrixStack, mouseX, mouseY); + final Layer layer = Layer.FOREGROUND; + + builder.drawMultiEnergyBar(matrixStack, this, 9, 19, (int) blockEntity.getEnergy(), (int) blockEntity.getMaxStoredPower(), mouseX, mouseY, 0, layer); + } +} diff --git a/src/main/java/techreborn/client/gui/GuiBlockPlacer.java b/src/main/java/techreborn/client/gui/GuiBlockPlacer.java new file mode 100644 index 000000000..974d88ab4 --- /dev/null +++ b/src/main/java/techreborn/client/gui/GuiBlockPlacer.java @@ -0,0 +1,68 @@ +/* + * This file is part of TechReborn, licensed under the MIT License (MIT). + * + * Copyright (c) 2020 TechReborn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package techreborn.client.gui; + +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerEntity; +import reborncore.client.gui.builder.GuiBase; +import reborncore.common.screen.BuiltScreenHandler; +import techreborn.blockentity.machine.tier0.block.BlockPlacerBlockEntity; +import techreborn.blockentity.machine.tier0.block.blockplacer.BlockPlacerProcessor; + +public class GuiBlockPlacer extends GuiBase { + + BlockPlacerBlockEntity blockEntity; + + public GuiBlockPlacer(int syncID, final PlayerEntity player, final BlockPlacerBlockEntity blockEntity) { + super(player, blockEntity, blockEntity.createScreenHandler(syncID, player)); + this.blockEntity = blockEntity; + } + + @Override + protected void drawBackground(MatrixStack matrixStack, final float f, final int mouseX, final int mouseY) { + super.drawBackground(matrixStack, f, mouseX, mouseY); + final Layer layer = Layer.BACKGROUND; + + BlockPlacerProcessor processor = blockEntity.getProcessor(); + + drawSlot(matrixStack, 8, 72, layer); + + drawCentredText(matrixStack, blockEntity.getProcessor().getStatusEnum().getText(), 25, processor.getStatusEnum().getColor(), layer); + + drawCentredText(matrixStack, processor.getStatusEnum().getProgressText(processor.getProgress()), 40, processor.getStatusEnum().getColor(), layer); + + drawSlot(matrixStack, 80, 60, layer); + + builder.drawJEIButton(matrixStack, this, 158, 5, layer); + } + + @Override + protected void drawForeground(MatrixStack matrixStack, final int mouseX, final int mouseY) { + super.drawForeground(matrixStack, mouseX, mouseY); + final Layer layer = Layer.FOREGROUND; + + builder.drawMultiEnergyBar(matrixStack, this, 9, 19, (int) blockEntity.getEnergy(), (int) blockEntity.getMaxStoredPower(), mouseX, mouseY, 0, layer); + } +} diff --git a/src/main/java/techreborn/config/TechRebornConfig.java b/src/main/java/techreborn/config/TechRebornConfig.java index 764527a81..0266b90d7 100644 --- a/src/main/java/techreborn/config/TechRebornConfig.java +++ b/src/main/java/techreborn/config/TechRebornConfig.java @@ -555,6 +555,30 @@ public class TechRebornConfig { @Config(config = "machines", category = "drain", key = "TicksUntilNextDrainAttempt", comment = "How many ticks should go between two drain attempts. 0 or negative will disable drain.") public static int ticksUntilNextDrainAttempt = 10; + @Config(config = "machines", category = "block_breaker", key = "BlockBreakerMaxInput", comment = "Block Breaker Max Input (Energy per tick)") + public static int blockBreakerMaxInput = 32; + + @Config(config = "machines", category = "block_breaker", key = "BlockBreakerMaxEnergy", comment = "Block Breaker Max Energy") + public static int blockBreakerMaxEnergy = 1_000; + + @Config(config = "machines", category = "block_breaker", key = "BlockBreakerEnergyPerTick", comment = "Block Breaker Energy usage Per Tick") + public static int blockBreakerEnergyPerTick = 5; + + @Config(config = "machines", category = "block_breaker", key = "BlockBreakerBaseBreakTime", comment = "How many ticks a block of hardness 1 requires to be broken") + public static int blockBreakerBaseBreakTime = 100; + + @Config(config = "machines", category = "block_placer", key = "BlockPlacerMaxInput", comment = "Block Placer Max Input (Energy per tick)") + public static int blockPlacerMaxInput = 32; + + @Config(config = "machines", category = "block_placer", key = "BlockPlacerMaxEnergy", comment = "Block Placer Max Energy") + public static int blockPlacerMaxEnergy = 1_000; + + @Config(config = "machines", category = "block_placer", key = "BlockPlacerEnergyPerTick", comment = "Block Placer Energy usage Per Tick") + public static int blockPlacerEnergyPerTick = 5; + + @Config(config = "machines", category = "block_placer", key = "BlockPlacerBaseBreakTime", comment = "How many ticks a block of hardness 1 requires to be placed") + public static int blockPlacerBaseBreakTime = 100; + // Misc @Config(config = "misc", category = "general", key = "IC2TransformersStyle", comment = "Input from dots side, output from other sides, like in IC2.") public static boolean IC2TransformersStyle = true; diff --git a/src/main/java/techreborn/init/ModSounds.java b/src/main/java/techreborn/init/ModSounds.java index baea2cfde..6e4d39a46 100644 --- a/src/main/java/techreborn/init/ModSounds.java +++ b/src/main/java/techreborn/init/ModSounds.java @@ -54,6 +54,7 @@ public class ModSounds { if (world == null) { return; } + world.playSound(null, blockEntity.getPos().getX(), blockEntity.getPos().getY(), blockEntity.getPos().getZ(), ModSounds.MACHINE_RUN, SoundCategory.BLOCKS, TechRebornConfig.machineSoundVolume, 1F); } diff --git a/src/main/java/techreborn/init/TRBlockEntities.java b/src/main/java/techreborn/init/TRBlockEntities.java index 712b555ec..1ccf4b8b5 100644 --- a/src/main/java/techreborn/init/TRBlockEntities.java +++ b/src/main/java/techreborn/init/TRBlockEntities.java @@ -51,6 +51,8 @@ import techreborn.blockentity.machine.misc.ChargeOMatBlockEntity; import techreborn.blockentity.machine.misc.DrainBlockEntity; import techreborn.blockentity.machine.multiblock.*; import techreborn.blockentity.machine.multiblock.casing.MachineCasingBlockEntity; +import techreborn.blockentity.machine.tier0.block.BlockBreakerBlockEntity; +import techreborn.blockentity.machine.tier0.block.BlockPlacerBlockEntity; import techreborn.blockentity.machine.tier1.*; import techreborn.blockentity.machine.tier3.ChunkLoaderBlockEntity; import techreborn.blockentity.machine.tier3.IndustrialCentrifugeBlockEntity; @@ -138,6 +140,8 @@ public class TRBlockEntities { public static final BlockEntityType SOLID_CANNING_MACHINE = register(SolidCanningMachineBlockEntity::new, "solid_canning_machine", TRContent.Machine.SOLID_CANNING_MACHINE); public static final BlockEntityType WIRE_MILL = register(WireMillBlockEntity::new, "wire_mill", TRContent.Machine.WIRE_MILL); public static final BlockEntityType GREENHOUSE_CONTROLLER = register(GreenhouseControllerBlockEntity::new, "greenhouse_controller", TRContent.Machine.GREENHOUSE_CONTROLLER); + public static final BlockEntityType BLOCK_BREAKER = register(BlockBreakerBlockEntity::new, "block_breaker", TRContent.Machine.BLOCK_BREAKER); + public static final BlockEntityType BLOCK_PLACER = register(BlockPlacerBlockEntity::new, "block_placer", TRContent.Machine.BLOCK_PLACER); public static BlockEntityType register(BiFunction supplier, String name, ItemConvertible... items) { return register(supplier, name, Arrays.stream(items).map(itemConvertible -> Block.getBlockFromItem(itemConvertible.asItem())).toArray(Block[]::new)); diff --git a/src/main/java/techreborn/init/TRContent.java b/src/main/java/techreborn/init/TRContent.java index c9a412df2..13e45a70c 100644 --- a/src/main/java/techreborn/init/TRContent.java +++ b/src/main/java/techreborn/init/TRContent.java @@ -47,8 +47,8 @@ import reborncore.common.fluid.FluidValue; import reborncore.common.misc.TagConvertible; import reborncore.common.powerSystem.PowerAcceptorBlockEntity; import reborncore.common.powerSystem.RcEnergyTier; - import techreborn.TechReborn; +import techreborn.blockentity.GuiType; import techreborn.blockentity.generator.LightningRodBlockEntity; import techreborn.blockentity.generator.PlasmaGeneratorBlockEntity; import techreborn.blockentity.generator.advanced.*; @@ -58,6 +58,8 @@ import techreborn.blockentity.generator.basic.WindMillBlockEntity; import techreborn.blockentity.machine.misc.ChargeOMatBlockEntity; import techreborn.blockentity.machine.misc.DrainBlockEntity; import techreborn.blockentity.machine.multiblock.*; +import techreborn.blockentity.machine.tier0.block.BlockBreakerBlockEntity; +import techreborn.blockentity.machine.tier0.block.BlockPlacerBlockEntity; import techreborn.blockentity.machine.tier1.*; import techreborn.blockentity.machine.tier3.ChunkLoaderBlockEntity; import techreborn.blockentity.machine.tier3.IndustrialCentrifugeBlockEntity; @@ -83,7 +85,6 @@ import techreborn.blocks.transformers.BlockEVTransformer; import techreborn.blocks.transformers.BlockHVTransformer; import techreborn.blocks.transformers.BlockLVTransformer; import techreborn.blocks.transformers.BlockMVTransformer; -import techreborn.blockentity.GuiType; import techreborn.config.TechRebornConfig; import techreborn.entities.EntityNukePrimed; import techreborn.events.ModRegistry; @@ -95,7 +96,6 @@ import techreborn.world.OreDistribution; import java.util.*; import java.util.function.Function; -import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -684,6 +684,8 @@ public class TRContent { SOLID_CANNING_MACHINE(new GenericMachineBlock(GuiType.SOLID_CANNING_MACHINE, SolidCanningMachineBlockEntity::new)), WIRE_MILL(new GenericMachineBlock(GuiType.WIRE_MILL, WireMillBlockEntity::new)), GREENHOUSE_CONTROLLER(new GenericMachineBlock(GuiType.GREENHOUSE_CONTROLLER, GreenhouseControllerBlockEntity::new)), + BLOCK_BREAKER(new GenericMachineBlock(GuiType.BLOCK_BREAKER, BlockBreakerBlockEntity::new)), + BLOCK_PLACER(new GenericMachineBlock(GuiType.BLOCK_PLACER, BlockPlacerBlockEntity::new)), DIESEL_GENERATOR(new GenericGeneratorBlock(GuiType.DIESEL_GENERATOR, DieselGeneratorBlockEntity::new)), DRAGON_EGG_SYPHON(new GenericGeneratorBlock(null, DragonEggSyphonBlockEntity::new)), diff --git a/src/main/resources/assets/techreborn/blockstates/block_breaker.json b/src/main/resources/assets/techreborn/blockstates/block_breaker.json new file mode 100644 index 000000000..9dad08f37 --- /dev/null +++ b/src/main/resources/assets/techreborn/blockstates/block_breaker.json @@ -0,0 +1,12 @@ +{ + "variants": { + "facing=north,active=false": { "model": "techreborn:block/machines/tier0_machines/block_breaker" }, + "facing=south,active=false": { "model": "techreborn:block/machines/tier0_machines/block_breaker", "y": 180 }, + "facing=west,active=false": { "model": "techreborn:block/machines/tier0_machines/block_breaker", "y": 270 }, + "facing=east,active=false": { "model": "techreborn:block/machines/tier0_machines/block_breaker", "y": 90 }, + "facing=north,active=true": { "model": "techreborn:block/machines/tier0_machines/block_breaker" }, + "facing=south,active=true": { "model": "techreborn:block/machines/tier0_machines/block_breaker", "y": 180 }, + "facing=west,active=true": { "model": "techreborn:block/machines/tier0_machines/block_breaker", "y": 270 }, + "facing=east,active=true": { "model": "techreborn:block/machines/tier0_machines/block_breaker", "y": 90 } + } +} diff --git a/src/main/resources/assets/techreborn/blockstates/block_placer.json b/src/main/resources/assets/techreborn/blockstates/block_placer.json new file mode 100644 index 000000000..727648a26 --- /dev/null +++ b/src/main/resources/assets/techreborn/blockstates/block_placer.json @@ -0,0 +1,12 @@ +{ + "variants": { + "facing=north,active=false": { "model": "techreborn:block/machines/tier0_machines/block_placer" }, + "facing=south,active=false": { "model": "techreborn:block/machines/tier0_machines/block_placer", "y": 180 }, + "facing=west,active=false": { "model": "techreborn:block/machines/tier0_machines/block_placer", "y": 270 }, + "facing=east,active=false": { "model": "techreborn:block/machines/tier0_machines/block_placer", "y": 90 }, + "facing=north,active=true": { "model": "techreborn:block/machines/tier0_machines/block_placer" }, + "facing=south,active=true": { "model": "techreborn:block/machines/tier0_machines/block_placer", "y": 180 }, + "facing=west,active=true": { "model": "techreborn:block/machines/tier0_machines/block_placer", "y": 270 }, + "facing=east,active=true": { "model": "techreborn:block/machines/tier0_machines/block_placer", "y": 90 } + } +} diff --git a/src/main/resources/assets/techreborn/lang/en_us.json b/src/main/resources/assets/techreborn/lang/en_us.json index bff7d2e38..50a45b544 100644 --- a/src/main/resources/assets/techreborn/lang/en_us.json +++ b/src/main/resources/assets/techreborn/lang/en_us.json @@ -91,6 +91,8 @@ "block.techreborn.solid_canning_machine": "Solid Canning Machine", "block.techreborn.wire_mill": "Wire Mill", "block.techreborn.greenhouse_controller": "Greenhouse controller", + "block.techreborn.block_breaker": "Block Breaker", + "block.techreborn.block_placer": "Block Placer", "_comment1": "Blocks", "block.techreborn.rubber_log": "Rubber Log", @@ -829,6 +831,8 @@ "techreborn.message.info.block.techreborn.charge_o_mat": "Charges up to 6 items simultaneously", "techreborn.message.info.block.techreborn.chunk_loader": "Keeps chunks loaded, allows machines to run when you're not nearby", "techreborn.message.info.block.techreborn.drain": "Pulls any fluid directly above it, pairs nicely with a tank unit underneath", + "techreborn.message.info.block.techreborn.block_breaker": "Breaks any block directly in front of it", + "techreborn.message.info.block.techreborn.block_placer": "Places blocks from its inventory directly in front of it", "keys.techreborn.category": "TechReborn Category", "keys.techreborn.config": "Config", @@ -857,8 +861,6 @@ "_comment20": "Death Messages", "death.attack.shock": "%s was electrocuted", "death.attack.shock.player": "%s was electrocuted trying to outrun %s", - "death.attack.fusion": "%s suffered from acute radiation sickness", - "death.attack.fusion.player": "%s suffered from acute radiation sickness trying to outrun %s", "_comment21": "Entities", "entity.nuke": "Nuke", @@ -1085,8 +1087,24 @@ "gui.techreborn.tank.amount": "Fluid Amount:", "gui.techreborn.storage.store": "Storing:", "gui.techreborn.storage.amount": "Amount:", + "gui.techreborn.fusion.norecipe": "No recipe", "gui.techreborn.fusion.charging": "Charging", - "gui.techreborn.fusion.chargingdetailed": "Charging (%s)", - "gui.techreborn.fusion.crafting": "Crafting" + "gui.techreborn.fusion.chargingdetailed": "Charging (%s)", + "gui.techreborn.fusion.crafting": "Crafting", + + "gui.techreborn.block_breaker.idle": "Nothing to break", + "gui.techreborn.block_breaker.processing": "Breaking block", + + "gui.techreborn.block_placer.idle": "Nothing to place", + "gui.techreborn.block_placer.processing": "Placing block", + + "gui.techreborn.block.idle_redstone": "Processing paused by redstone", + "gui.techreborn.block.output_full": "Output is full", + "gui.techreborn.block.no_energy": "Not enough energy", + "gui.techreborn.block.interrupted": "Interrupted", + "gui.techreborn.block.output_blocked": "Output blocked", + "gui.techreborn.block.progress.active": "Progress: (%s)", + "gui.techreborn.block.progress.stopped": "Idle (Stopped)", + "gui.techreborn.block.progress.paused": "Idle (%s)" } \ No newline at end of file diff --git a/src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_breaker.json b/src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_breaker.json new file mode 100644 index 000000000..361cf2527 --- /dev/null +++ b/src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_breaker.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "top": "techreborn:block/machines/tier0_machines/machine_top", + "front": "techreborn:block/machines/tier0_machines/block_breaker_front", + "side": "techreborn:block/machines/tier0_machines/machine_side" + } +} diff --git a/src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_placer.json b/src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_placer.json new file mode 100644 index 000000000..b51672a70 --- /dev/null +++ b/src/main/resources/assets/techreborn/models/block/machines/tier0_machines/block_placer.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "top": "techreborn:block/machines/tier0_machines/machine_top", + "front": "techreborn:block/machines/tier0_machines/block_placer_front", + "side": "techreborn:block/machines/tier0_machines/machine_side" + } +} diff --git a/src/main/resources/assets/techreborn/models/item/block_breaker.json b/src/main/resources/assets/techreborn/models/item/block_breaker.json new file mode 100644 index 000000000..3dfd74c40 --- /dev/null +++ b/src/main/resources/assets/techreborn/models/item/block_breaker.json @@ -0,0 +1,3 @@ +{ + "parent": "techreborn:block/machines/tier0_machines/block_breaker" +} \ No newline at end of file diff --git a/src/main/resources/assets/techreborn/models/item/block_placer.json b/src/main/resources/assets/techreborn/models/item/block_placer.json new file mode 100644 index 000000000..126da413c --- /dev/null +++ b/src/main/resources/assets/techreborn/models/item/block_placer.json @@ -0,0 +1,3 @@ +{ + "parent": "techreborn:block/machines/tier0_machines/block_placer" +} \ No newline at end of file diff --git a/src/main/resources/assets/techreborn/textures/block/machines/tier0_machines/block_breaker_front.png b/src/main/resources/assets/techreborn/textures/block/machines/tier0_machines/block_breaker_front.png new file mode 100644 index 0000000000000000000000000000000000000000..19df162f9c996d83883f3b8b1e780780f0490c85 GIT binary patch literal 711 zcmV;&0yzDNP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf0$fQ%K~y+Tl~YS= z6HyfY?wvc+m}I43YYlA_g#3Z5N+@JiLjH~5#+~3obmLEOKbc$3HH<&DZO290ws~0U;p;{cx&`Znuk#jSY-OBl}-2m+hG)gLR!w z$7aWTu~eD~quTg_v+4DE7z_qzG#WTMIGa!CENJSaAM9g?RCbESM z!YQ^|Eo^OV*;m<_bs0F2)*%A=WT+#Yo(K4Kd~B6cO3OO8lbt;32H#x{5YS^M=ixMi z55pneyx)Ys|7E8BH%_VLFIwx^9qv$Y;o#=N{7m&HvYMHn%iwHpEG)vL31p-LOvpfo z!Aw2H+S(dcR#s50R?%!WXSY*C+y!!GsnTSEaS%|n>9EvlHS73y3oDh%MH|`HBaT=q zL)_3ZU_wUqdfhrRGUrTYffzJG2&p{w5%(WIHMf_`=u_|i2c^;?4!?bexclIdxwX7R zy_bli1Xqd$gv1ALC(k^$(4~bMQ`>|vNNEFkR=hcdJ%114-oqzG)28WITcty_#gT?| tTpLuPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf0!B$hK~y+Tl~c=# zQ$Y|t-S=V4Ya{45hM6b``GKrL5V8uvKhc$fn^`&FLUiMo2r40e;3;`h^ z0H`=Y9LLDz^M;coDa7#oM}2*#gynLHY&J_Y7?S7vhU9x5wAQ9jOa)xmfl> z2N16hk96tc1sqI2n`8?vlBOwG9b1cp_G40dvvC8@dVRP|$Ye4mxPRxiv46v@z557B z1%!kYj$@=U7K;T!zB8fOY@%ANn#DeYW6WW7+%LAS;)c=Pc!N=|*HNq0P%f7-o6U@6 zR4Nq=1_N}v-ObfBs6RgU#DPbRS*=!RG#VzEVUw-3g&3?@sSp7z8L9}2vjE>uPfgI0 zZNi_4)(_~gA7`OaAm2?Uc=_fnrYE0F@L#Z?Cx80lIgTcWkkmz7*}C*Aw2^LMeYSQn zSncJlZRj+Cj8uR%HBf~CdcB@$lqIrc_N{c=#E4&klG(axvc@V1sM=;|`u#peqY+xI z7UuK0Nt{lnXt&$HpPRWpjXYbaX~^j_U`>Hyv1o=$N{LRVgYkH57W=%%u|lC>xFHo| zEA}2e(bsm%7}BZ#gHmZ5U%q~WxV!&QU)|k-<4D9&g7f(tOCeMSU!J{uqTn|41 XD6VI^$oplX00000NkvXXu0mjfdk-*B literal 0 HcmV?d00001 diff --git a/src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_breaker.json b/src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_breaker.json new file mode 100644 index 000000000..914904cf5 --- /dev/null +++ b/src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_breaker.json @@ -0,0 +1,54 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "techreborn:crafting_table/machine/block_breaker" + ] + }, + "criteria": { + "has_sticky_piston": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["minecraft:sticky_piston"] + } + ] + } + }, + "has_refined_iron_plate": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["techreborn:refined_iron_plate"] + } + ] + } + }, + "has_hopper": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["minecraft:hopper"] + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "techreborn:crafting_table/machine/block_breaker" + } + } + }, + "requirements": [ + [ + "has_sticky_piston", + "has_refined_iron_plate", + "has_hopper", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_placer.json b/src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_placer.json new file mode 100644 index 000000000..0b0f77132 --- /dev/null +++ b/src/main/resources/data/techreborn/advancements/recipes/crafting_table/machine/block_placer.json @@ -0,0 +1,54 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "techreborn:crafting_table/machine/block_placer" + ] + }, + "criteria": { + "has_piston": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["minecraft:piston"] + } + ] + } + }, + "has_refined_iron_plate": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["techreborn:refined_iron_plate"] + } + ] + } + }, + "has_hopper": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "items": ["minecraft:hopper"] + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "techreborn:crafting_table/machine/block_placer" + } + } + }, + "requirements": [ + [ + "has_piston", + "has_refined_iron_plate", + "has_hopper", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/main/resources/data/techreborn/loot_tables/blocks/block_breaker.json b/src/main/resources/data/techreborn/loot_tables/blocks/block_breaker.json new file mode 100644 index 000000000..1392c4208 --- /dev/null +++ b/src/main/resources/data/techreborn/loot_tables/blocks/block_breaker.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "techreborn:block_breaker" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/techreborn/loot_tables/blocks/block_placer.json b/src/main/resources/data/techreborn/loot_tables/blocks/block_placer.json new file mode 100644 index 000000000..81f0c72af --- /dev/null +++ b/src/main/resources/data/techreborn/loot_tables/blocks/block_placer.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "techreborn:block_placer" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/techreborn/recipes/crafting_table/machine/block_breaker.json b/src/main/resources/data/techreborn/recipes/crafting_table/machine/block_breaker.json new file mode 100644 index 000000000..0d1a8c255 --- /dev/null +++ b/src/main/resources/data/techreborn/recipes/crafting_table/machine/block_breaker.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "PCP", + "PHP", + "PXP" + ], + "key": { + "P": { + "item": "techreborn:refined_iron_plate" + }, + "C": { + "item": "techreborn:electronic_circuit" + }, + "H": { + "item": "minecraft:hopper" + }, + "X": { + "item": "minecraft:sticky_piston" + } + }, + "result": { + "item": "techreborn:block_breaker" + } +} \ No newline at end of file diff --git a/src/main/resources/data/techreborn/recipes/crafting_table/machine/block_placer.json b/src/main/resources/data/techreborn/recipes/crafting_table/machine/block_placer.json new file mode 100644 index 000000000..fc9216ad2 --- /dev/null +++ b/src/main/resources/data/techreborn/recipes/crafting_table/machine/block_placer.json @@ -0,0 +1,25 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "PCP", + "PHP", + "PXP" + ], + "key": { + "P": { + "item": "techreborn:refined_iron_plate" + }, + "C": { + "item": "techreborn:electronic_circuit" + }, + "H": { + "item": "minecraft:hopper" + }, + "X": { + "item": "minecraft:piston" + } + }, + "result": { + "item": "techreborn:block_placer" + } +} \ No newline at end of file