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
This commit is contained in:
parent
c8ca8a5aa3
commit
7f2912009b
38 changed files with 1543 additions and 10 deletions
|
@ -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<T extends BlockEntity> implements IMachineGuiHandler
|
|||
public static final GuiType<FluidReplicatorBlockEntity> FLUID_REPLICATOR = register("fluid_replicator");
|
||||
public static final GuiType<PlayerDetectorBlockEntity> PLAYER_DETECTOR = register("player_detector");
|
||||
public static final GuiType<DataDrivenBEProvider.DataDrivenBlockEntity> DATA_DRIVEN = register("data_driven");
|
||||
public static final GuiType<BlockBreakerBlockEntity> BLOCK_BREAKER = register("block_breaker");
|
||||
public static final GuiType<BlockPlacerBlockEntity> BLOCK_PLACER = register("block_placer");
|
||||
|
||||
private static <T extends BlockEntity> GuiType<T> register(String id) {
|
||||
return register(new Identifier("techreborn", id));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>A machine that can break the block physically located in front of it</b>
|
||||
* <br>
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>A machine that can break place blocks in front of it</b>
|
||||
* <br>
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>Aggregated interface for use with BlockEntities that have a processor attached</b>
|
||||
* <br>
|
||||
* Example of a processor {@link techreborn.blockentity.machine.tier0.block.blockplacer.BlockPlacerProcessor}
|
||||
*
|
||||
* @author SimonFlapse
|
||||
*/
|
||||
public interface BlockProcessable extends IUpgradeHandler, RedstoneConfigurable, InventoryProvider {
|
||||
/**
|
||||
* <b>Consume some amount of Energy</b>
|
||||
* <br>
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
* <b>Play a sound to the Minecraft world</b>
|
||||
*/
|
||||
void playSound();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>Common utilities for BlockProcessors</b>
|
||||
* <br>
|
||||
* Only exposes static methods
|
||||
*
|
||||
* @author SimonFlapse
|
||||
*/
|
||||
public class BlockProcessorUtils {
|
||||
private BlockProcessorUtils() {};
|
||||
|
||||
/**
|
||||
* <b>Get the hardness to break of a block</b>
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <b>Get processing time adjusted to the hardness of a block and the overclocking speed</b>
|
||||
* <br>
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Play a sound in a regular interval of 20 ticks</b>
|
||||
* <br>
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Get the position of the block in front of the blockEntity</b>
|
||||
* <br>
|
||||
* @param blockEntity
|
||||
* @param pos
|
||||
* @return
|
||||
*/
|
||||
public static BlockPos getFrontBlockPosition(MachineBaseBlockEntity blockEntity, BlockPos pos) {
|
||||
return pos.offset(blockEntity.getFacing() == null? Direction.NORTH : blockEntity.getFacing());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package techreborn.blockentity.machine.tier0.block;
|
||||
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
/**
|
||||
* <b>Interface describing different statuses of a Processing Machine</b>
|
||||
* <br>
|
||||
* Used to define {@link TranslatableText} for UI elements based on the positive, neutral or negative status of a machine
|
||||
*
|
||||
* @author SimonFlapse
|
||||
*/
|
||||
public interface ProcessingStatus {
|
||||
/**
|
||||
* <b>The status state described as a translatable text</b>
|
||||
*
|
||||
* @return The translatable text for displaying in a UI
|
||||
*/
|
||||
Text getText();
|
||||
|
||||
/**
|
||||
* <b>The processing status with current progress formatted</b>
|
||||
* <br>
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* <b>The color to be used for the status text</b>
|
||||
* <br>
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* <b>Integer representation of a status</b>
|
||||
* <br>
|
||||
* Similar to, or fully based on {@link Enum#ordinal()}
|
||||
*
|
||||
* @return an integer corresponding to the status code
|
||||
* @see Enum#ordinal()
|
||||
*/
|
||||
int getStatusCode();
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>Class handling Nbt values of the Block Breaker</b>
|
||||
* <br>
|
||||
* 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];
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>Class handling the process of breaking a block</b>
|
||||
* <br>
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>Class handling Nbt values of the Block Placer</b>
|
||||
* <br>
|
||||
* 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];
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <b>Class handling the process of placing a block</b>
|
||||
* <br>
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<T extends BlockEntity> {
|
|||
public static final ClientGuiType<FluidReplicatorBlockEntity> FLUID_REPLICATOR = register(GuiType.FLUID_REPLICATOR, GuiFluidReplicator::new);
|
||||
public static final ClientGuiType<PlayerDetectorBlockEntity> PLAYER_DETECTOR = register(GuiType.PLAYER_DETECTOR, GuiPlayerDetector::new);
|
||||
public static final ClientGuiType<DataDrivenBEProvider.DataDrivenBlockEntity> DATA_DRIVEN = register(GuiType.DATA_DRIVEN, DataDrivenGui::new);
|
||||
public static final ClientGuiType<BlockBreakerBlockEntity> BLOCK_BREAKER = register(GuiType.BLOCK_BREAKER, GuiBlockBreaker::new);
|
||||
public static final ClientGuiType<BlockPlacerBlockEntity> BLOCK_PLACER = register(GuiType.BLOCK_PLACER, GuiBlockPlacer::new);
|
||||
|
||||
private static <T extends BlockEntity> ClientGuiType<T> register(GuiType<T> type, GuiFactory<T> factory) {
|
||||
return new ClientGuiType<>(type, factory);
|
||||
|
|
68
src/main/java/techreborn/client/gui/GuiBlockBreaker.java
Normal file
68
src/main/java/techreborn/client/gui/GuiBlockBreaker.java
Normal file
|
@ -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<BuiltScreenHandler> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
68
src/main/java/techreborn/client/gui/GuiBlockPlacer.java
Normal file
68
src/main/java/techreborn/client/gui/GuiBlockPlacer.java
Normal file
|
@ -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<BuiltScreenHandler> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<SolidCanningMachineBlockEntity> SOLID_CANNING_MACHINE = register(SolidCanningMachineBlockEntity::new, "solid_canning_machine", TRContent.Machine.SOLID_CANNING_MACHINE);
|
||||
public static final BlockEntityType<WireMillBlockEntity> WIRE_MILL = register(WireMillBlockEntity::new, "wire_mill", TRContent.Machine.WIRE_MILL);
|
||||
public static final BlockEntityType<GreenhouseControllerBlockEntity> GREENHOUSE_CONTROLLER = register(GreenhouseControllerBlockEntity::new, "greenhouse_controller", TRContent.Machine.GREENHOUSE_CONTROLLER);
|
||||
public static final BlockEntityType<BlockBreakerBlockEntity> BLOCK_BREAKER = register(BlockBreakerBlockEntity::new, "block_breaker", TRContent.Machine.BLOCK_BREAKER);
|
||||
public static final BlockEntityType<BlockPlacerBlockEntity> BLOCK_PLACER = register(BlockPlacerBlockEntity::new, "block_placer", TRContent.Machine.BLOCK_PLACER);
|
||||
|
||||
public static <T extends BlockEntity> BlockEntityType<T> register(BiFunction<BlockPos, BlockState, T> supplier, String name, ItemConvertible... items) {
|
||||
return register(supplier, name, Arrays.stream(items).map(itemConvertible -> Block.getBlockFromItem(itemConvertible.asItem())).toArray(Block[]::new));
|
||||
|
|
|
@ -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)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue