mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 01:50:56 +01:00
Basic framework for vacuum arc furnace multiblock. Moved multiblock methods to MultiblockHelper.
This commit is contained in:
@@ -2,6 +2,11 @@ package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -13,13 +18,17 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.xevianlight.aphelion.block.entity.custom.EAFPartEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||
import net.xevianlight.aphelion.util.MultiblockHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ArcFurnaceCasingBlock extends BaseEntityBlock {
|
||||
|
||||
public static final BooleanProperty FORMED = BooleanProperty.create("formed");
|
||||
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
||||
|
||||
public ArcFurnaceCasingBlock(Properties properties) {
|
||||
super(properties);
|
||||
@@ -27,6 +36,11 @@ public class ArcFurnaceCasingBlock extends BaseEntityBlock {
|
||||
.setValue(FORMED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
return Properties
|
||||
.of()
|
||||
@@ -42,18 +56,18 @@ public class ArcFurnaceCasingBlock extends BaseEntityBlock {
|
||||
|
||||
public static final MapCodec<ArcFurnaceCasingBlock> CODEC = simpleCodec(ArcFurnaceCasingBlock::new);
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
// @Override
|
||||
// protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
// return CODEC;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new EAFPartEntity(blockPos, blockState);
|
||||
}
|
||||
// @Override
|
||||
// public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
// return new EAFPartEntity(blockPos, blockState);
|
||||
// }
|
||||
|
||||
private void pingNearbyController(Level level, BlockPos pos) {
|
||||
int r = 3;
|
||||
int r = 5;
|
||||
BlockPos.MutableBlockPos mp = new BlockPos.MutableBlockPos();
|
||||
|
||||
for (int dx=-r; dx<=r; dx++)
|
||||
@@ -61,14 +75,28 @@ public class ArcFurnaceCasingBlock extends BaseEntityBlock {
|
||||
for (int dz=-r; dz<=r; dz++) {
|
||||
mp.set(pos.getX()+dx, pos.getY()+dy, pos.getZ()+dz);
|
||||
BlockEntity be = level.getBlockEntity(mp);
|
||||
if (be instanceof ElectricArcFurnaceEntity eaf) {
|
||||
if (level.getBlockState(eaf.getBlockPos()).getBlock() instanceof ElectricArcFurnace) {
|
||||
eaf.tryForm();
|
||||
if (be instanceof VacuumArcFurnaceControllerEntity vaf) {
|
||||
if (level.getBlockState(vaf.getBlockPos()).getBlock() instanceof VacuumArcFurnaceController) {
|
||||
MultiblockHelper.tryForm(level, vaf.getBlockState(), vaf.getBlockPos(), VacuumArcFurnaceControllerEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
if (state.getValue(AphelionBlockStateProperties.FORMED)) {
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof EAFPartEntity eafPartEntity) {
|
||||
if (eafPartEntity.getControllerPos() != null)
|
||||
if (level.getBlockEntity(eafPartEntity.getControllerPos()) instanceof VacuumArcFurnaceControllerEntity)
|
||||
serverPlayer.openMenu(new SimpleMenuProvider((VacuumArcFurnaceControllerEntity) level.getBlockEntity(eafPartEntity.getControllerPos()), Component.literal("Vacuum Arc Furnace")), eafPartEntity.getControllerPos());
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||
@@ -97,4 +125,9 @@ public class ArcFurnaceCasingBlock extends BaseEntityBlock {
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FORMED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new EAFPartEntity(blockPos, blockState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||
import net.xevianlight.aphelion.util.MultiblockHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -36,7 +38,7 @@ public class ElectricArcFurnace extends BaseEntityBlock {
|
||||
|
||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||
public static final BooleanProperty FORMED = BooleanProperty.create("formed");
|
||||
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
||||
|
||||
public ElectricArcFurnace(Properties properties) {
|
||||
super(properties);
|
||||
@@ -72,8 +74,8 @@ public class ElectricArcFurnace extends BaseEntityBlock {
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity && state.getValue(FORMED)) {
|
||||
serverPlayer.openMenu(new SimpleMenuProvider(electricArcFurnaceEntity, Component.literal("Electric Arc Furnace")), pos);
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
|
||||
serverPlayer.openMenu(new SimpleMenuProvider(electricArcFurnaceEntity, Component.literal("Electric Arc Furnace")), pos);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
@@ -95,7 +97,7 @@ public class ElectricArcFurnace extends BaseEntityBlock {
|
||||
if (!level.isClientSide && state.getBlock() != newState.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
|
||||
if(state.getValue(FORMED)) electricArcFurnaceEntity.unformForRemoval();
|
||||
// if(state.getValue(FORMED)) MultiblockHelper.unformForRemoval(level, state, pos, ElectricArcFurnaceEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
||||
electricArcFurnaceEntity.drops();
|
||||
}
|
||||
}
|
||||
@@ -107,9 +109,9 @@ public class ElectricArcFurnace extends BaseEntityBlock {
|
||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||
if (!level.isClientSide() && oldState.getBlock() != state.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
|
||||
electricArcFurnaceEntity.tryForm();
|
||||
}
|
||||
// if (blockEntity instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
|
||||
// MultiblockHelper.tryForm(level, state, pos, ElectricArcFurnaceEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||
import net.xevianlight.aphelion.util.MultiblockHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class VacuumArcFurnaceController extends BaseEntityBlock {
|
||||
|
||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
||||
|
||||
public VacuumArcFurnaceController(Properties properties) {
|
||||
super(properties);
|
||||
this.registerDefaultState(this.getStateDefinition().any()
|
||||
.setValue(FORMED, false));
|
||||
}
|
||||
|
||||
public static final MapCodec<VacuumArcFurnaceController> CODEC = simpleCodec(VacuumArcFurnaceController::new);
|
||||
|
||||
private final int INPUT_SLOT = 0;
|
||||
private final int SECONDARY_INPUT_SLOT = 1;
|
||||
private final int OUTPUT_SLOT = 2;
|
||||
private final int ENERGY_SLOT = 3;
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
public static Properties getProperties() {
|
||||
return Properties
|
||||
.of()
|
||||
.sound(SoundType.METAL)
|
||||
.destroyTime(2f)
|
||||
.explosionResistance(10f)
|
||||
.requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
public static Item.Properties getItemProperties() {
|
||||
return new Item.Properties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
||||
if (vacuumArcFurnaceEntity.isFormed())
|
||||
serverPlayer.openMenu(new SimpleMenuProvider(vacuumArcFurnaceEntity, Component.literal("Vacuum Arc Furnace")), pos);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new VacuumArcFurnaceControllerEntity(blockPos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState pState) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (!level.isClientSide && state.getBlock() != newState.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
||||
if(state.getValue(FORMED)) MultiblockHelper.unformForRemoval(level, state, pos, vacuumArcFurnaceEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
||||
vacuumArcFurnaceEntity.drops();
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||
if (!level.isClientSide() && oldState.getBlock() != state.getBlock()) {
|
||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
||||
MultiblockHelper.tryForm(level, state, pos, vacuumArcFurnaceEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getRedstoneSignalFromItemHandler(@javax.annotation.Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
|
||||
if (itemStackHandler == null) {
|
||||
return 0;
|
||||
} else {
|
||||
int i = 0;
|
||||
float f = 0.0F;
|
||||
|
||||
for(int slot : slots) {
|
||||
ItemStack itemstack = itemStackHandler.getStackInSlot(slot);
|
||||
if (!itemstack.isEmpty()) {
|
||||
f += (float)itemstack.getCount() / (float)Math.min(itemStackHandler.getSlotLimit(slot), itemstack.getMaxStackSize());
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
f /= (float)slots.size();
|
||||
return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSignalSource(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
||||
return super.getSignal(state, level, pos, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasAnalogOutputSignal(BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
|
||||
List<Integer> slots = new ArrayList<>();
|
||||
slots.add(VacuumArcFurnaceControllerEntity.INPUT_SLOT);
|
||||
slots.add(VacuumArcFurnaceControllerEntity.SECONDARY_INPUT_SLOT);
|
||||
slots.add(VacuumArcFurnaceControllerEntity.OUTPUT_SLOT);
|
||||
VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity = ((VacuumArcFurnaceControllerEntity) level.getBlockEntity(pos));
|
||||
|
||||
if (vacuumArcFurnaceEntity != null)
|
||||
return getRedstoneSignalFromItemHandler(vacuumArcFurnaceEntity.inventory, slots);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||
if (level.isClientSide) {
|
||||
return null;
|
||||
}
|
||||
return createTickerHelper(blockEntityType, ModBlockEntities.VACUUM_ARC_FURNACE_ENTITY.get(), (level1, blockPos, blockState, vacuumArcFurnaceEntity) -> vacuumArcFurnaceEntity.tick(level1, blockPos, blockState));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||
return state.rotate(mirror.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false).setValue(FORMED, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, LIT, FORMED);
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,10 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.util.IMultiblockPart;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class EAFPartEntity extends BlockEntity {
|
||||
public class EAFPartEntity extends BlockEntity implements IMultiblockPart {
|
||||
@Nullable private BlockPos controllerPos;
|
||||
|
||||
public EAFPartEntity(BlockPos pos, BlockState blockState) {
|
||||
|
||||
@@ -8,12 +8,9 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
@@ -23,26 +20,24 @@ import net.minecraft.world.item.crafting.*;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.custom.ArcFurnaceCasingBlock;
|
||||
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
|
||||
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
||||
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipe;
|
||||
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipeInput;
|
||||
import net.xevianlight.aphelion.recipe.ModRecipes;
|
||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
|
||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||
import net.xevianlight.aphelion.util.MultiblockHelper;
|
||||
import net.xevianlight.aphelion.util.SidedSlotHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider {
|
||||
|
||||
@@ -108,7 +103,7 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
||||
|
||||
public void tick(Level level, BlockPos pos, BlockState blockState) {
|
||||
|
||||
if (!blockState.getValue(ElectricArcFurnace.FORMED))
|
||||
if (!blockState.getValue(AphelionBlockStateProperties.FORMED))
|
||||
return;
|
||||
|
||||
chargeFromItem();
|
||||
@@ -316,6 +311,7 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
||||
}
|
||||
|
||||
private final IItemHandler fullHandler = new SidedSlotHandler(inventory, new int[]{INPUT_SLOT, SECONDARY_INPUT_SLOT, OUTPUT_SLOT, ENERGY_SLOT}, true, true);
|
||||
private final IItemHandler emptyJeiHandler = new SidedSlotHandler(inventory, new int[]{}, false, false);
|
||||
private final IItemHandler inputHandler = new SidedSlotHandler(inventory, new int[]{0,1}, true, true);
|
||||
private final IItemHandler outputHandler = new SidedSlotHandler(inventory, new int[]{2,3}, false, true);
|
||||
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
|
||||
@@ -325,13 +321,18 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
||||
}
|
||||
|
||||
public IEnergyStorage getEnergyStorage(@Nullable Direction direction) {
|
||||
return ENERGY_STORAGE;
|
||||
}
|
||||
|
||||
public IEnergyStorage getTrueEnergyStorage(@Nullable Direction direction) {
|
||||
return this.ENERGY_STORAGE;
|
||||
}
|
||||
|
||||
private final ModEnergyStorage ENERGY_STORAGE = createEnergyStorage();
|
||||
private final ModEnergyStorage ENERGY_STORAGE = createEnergyStorage(ENERGY_CAPACITY, MAX_TRANSFER);
|
||||
private final ModEnergyStorage NULL_ENERGY_STORAGE = createEnergyStorage(0, 0);
|
||||
|
||||
private ModEnergyStorage createEnergyStorage() {
|
||||
return new ModEnergyStorage(ENERGY_CAPACITY, MAX_TRANSFER) {
|
||||
private ModEnergyStorage createEnergyStorage(int capacity, int transfer) {
|
||||
return new ModEnergyStorage(capacity, transfer) {
|
||||
@Override
|
||||
public void onEnergyChanged() {
|
||||
setChanged();
|
||||
@@ -378,7 +379,7 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
||||
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -403,132 +404,8 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// MULTIBLOCK
|
||||
/// LOGIC
|
||||
/// BELOW
|
||||
|
||||
|
||||
|
||||
private boolean formed = false; // cached runtime state
|
||||
|
||||
private static final BlockPos[] SHAPE = new BlockPos[] {
|
||||
new BlockPos(1, 0, 0),
|
||||
new BlockPos(0, 0, 1),
|
||||
new BlockPos(1, 0, 1),
|
||||
|
||||
new BlockPos(0, 1, 0),
|
||||
new BlockPos(1, 1, 0),
|
||||
new BlockPos(0, 1, 1),
|
||||
new BlockPos(1, 1, 1),
|
||||
public static final MultiblockHelper.ShapePart[] SHAPE = new MultiblockHelper.ShapePart[] {
|
||||
new MultiblockHelper.ShapePart(new BlockPos(3,0,3), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
// new MultiblockHelper.ShapePart(new BlockPos(-1,0,0), s -> s.is(Blocks.AMETHYST_BLOCK))
|
||||
};
|
||||
|
||||
private List<BlockPos> getPartPositions() {
|
||||
Direction facing = getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
BlockPos origin = getBlockPos();
|
||||
|
||||
List<BlockPos> out = new ArrayList<>(SHAPE.length);
|
||||
for (BlockPos off : SHAPE) {
|
||||
BlockPos ro = rotateY(off, facing);
|
||||
out.add(origin.offset(ro));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private boolean structureMatches() {
|
||||
if (level == null) return false;
|
||||
|
||||
for (BlockPos p : getPartPositions()) {
|
||||
BlockState st = level.getBlockState(p);
|
||||
|
||||
// Accept only your casing/part blocks
|
||||
if (!(st.getBlock() instanceof ArcFurnaceCasingBlock)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFormed() {
|
||||
return formed;
|
||||
}
|
||||
|
||||
public void tryForm() {
|
||||
if (level == null || level.isClientSide()) return;
|
||||
if (!(getBlockState().getBlock() instanceof ElectricArcFurnace)) return; // don't form if not actually present
|
||||
|
||||
boolean valid = structureMatches();
|
||||
|
||||
if (valid && !formed) {
|
||||
formed = true;
|
||||
setFormedState(true);
|
||||
linkParts();
|
||||
} else if (!valid && formed) {
|
||||
unform();
|
||||
}
|
||||
}
|
||||
|
||||
public void unform() {
|
||||
if (level == null || level.isClientSide()) return;
|
||||
|
||||
formed = false;
|
||||
setFormedState(false);
|
||||
unlinkParts();
|
||||
}
|
||||
|
||||
public void unformForRemoval() {
|
||||
if (level == null || level.isClientSide()) return;
|
||||
|
||||
formed = false;
|
||||
unlinkParts();
|
||||
}
|
||||
|
||||
private void setFormedState(boolean value) {
|
||||
BlockState state = getBlockState();
|
||||
if (state.hasProperty(ElectricArcFurnace.FORMED) && state.getValue(ElectricArcFurnace.FORMED) != value) {
|
||||
level.setBlock(worldPosition, state.setValue(ElectricArcFurnace.FORMED, value), 3);
|
||||
}
|
||||
}
|
||||
|
||||
private void linkParts() {
|
||||
if (level == null || level.isClientSide()) return;
|
||||
|
||||
for (BlockPos p : getPartPositions()) {
|
||||
BlockState st = level.getBlockState(p);
|
||||
|
||||
if (st.getBlock() instanceof ArcFurnaceCasingBlock && st.hasProperty(ArcFurnaceCasingBlock.FORMED)) {
|
||||
if (!st.getValue(ArcFurnaceCasingBlock.FORMED)) {
|
||||
level.setBlock(p, st.setValue(ArcFurnaceCasingBlock.FORMED, true), 3);
|
||||
}
|
||||
}
|
||||
|
||||
BlockEntity be = level.getBlockEntity(p);
|
||||
if (be instanceof EAFPartEntity part) {
|
||||
part.setControllerPos(worldPosition);
|
||||
part.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unlinkParts() {
|
||||
if (level == null || level.isClientSide()) return;
|
||||
|
||||
for (BlockPos p : getPartPositions()) {
|
||||
BlockState st = level.getBlockState(p);
|
||||
|
||||
if (st.getBlock() instanceof ArcFurnaceCasingBlock && st.hasProperty(ArcFurnaceCasingBlock.FORMED)) {
|
||||
if (st.getValue(ArcFurnaceCasingBlock.FORMED)) {
|
||||
level.setBlock(p, st.setValue(ArcFurnaceCasingBlock.FORMED, false), 3);
|
||||
}
|
||||
}
|
||||
|
||||
BlockEntity be = level.getBlockEntity(p);
|
||||
if (be instanceof EAFPartEntity part && worldPosition.equals(part.getControllerPos())) {
|
||||
part.setControllerPos(null);
|
||||
part.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,507 @@
|
||||
package net.xevianlight.aphelion.block.entity.custom;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.BlastingRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.crafting.SingleRecipeInput;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
|
||||
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
||||
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipe;
|
||||
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipeInput;
|
||||
import net.xevianlight.aphelion.recipe.ModRecipes;
|
||||
import net.xevianlight.aphelion.screen.VacuumArcFurnaceMenu;
|
||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
|
||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||
import net.xevianlight.aphelion.util.IMultiblockController;
|
||||
import net.xevianlight.aphelion.util.MultiblockHelper;
|
||||
import net.xevianlight.aphelion.util.SidedSlotHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class VacuumArcFurnaceControllerEntity extends BlockEntity implements MenuProvider, IMultiblockController {
|
||||
|
||||
private final int SIZE = 4;
|
||||
private int ENERGY_CAPACITY = 64000;
|
||||
private int MAX_TRANSFER = 320;
|
||||
private int progress = 0;
|
||||
private int maxProgress = 100;
|
||||
private final int DEFAULT_MAX_PROGRESS = 100;
|
||||
private final ContainerData data;
|
||||
private int MACHINE_ENERGY_COST = 20;
|
||||
|
||||
public static final int INPUT_SLOT = 0;
|
||||
public static final int SECONDARY_INPUT_SLOT = 1;
|
||||
public static final int OUTPUT_SLOT = 2;
|
||||
public static final int ENERGY_SLOT = 3;
|
||||
|
||||
public VacuumArcFurnaceControllerEntity(BlockPos pos, BlockState blockState) {
|
||||
super(ModBlockEntities.VACUUM_ARC_FURNACE_ENTITY.get(), pos, blockState);
|
||||
this.data = new ContainerData() {
|
||||
@Override
|
||||
public int get(int index) {
|
||||
return switch (index) {
|
||||
case 0 -> VacuumArcFurnaceControllerEntity.this.progress;
|
||||
case 1 -> VacuumArcFurnaceControllerEntity.this.maxProgress;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, int pValue) {
|
||||
switch (index) {
|
||||
case 0: VacuumArcFurnaceControllerEntity.this.progress = pValue;
|
||||
case 1: VacuumArcFurnaceControllerEntity.this.maxProgress = pValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
|
||||
@Override
|
||||
protected void onContentsChanged(int slot) {
|
||||
setChanged();
|
||||
if(!level.isClientSide()) {
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean isItemValid(int slot, ItemStack stack) {
|
||||
// if (slot == ENERGY_SLOT) {
|
||||
// var capability = stack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
// return capability != null;
|
||||
// }
|
||||
// return super.isItemValid(slot, stack);
|
||||
// }
|
||||
};
|
||||
|
||||
public void tick(Level level, BlockPos pos, BlockState blockState) {
|
||||
|
||||
if (!blockState.getValue(AphelionBlockStateProperties.FORMED))
|
||||
return;
|
||||
|
||||
chargeFromItem();
|
||||
|
||||
if (inventory.getStackInSlot(SECONDARY_INPUT_SLOT).isEmpty()) {
|
||||
// Secondary slot is empty, try furnace recipes
|
||||
if (hasFurnaceRecipe(INPUT_SLOT) && hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
||||
// Recipe detected! We have enough energy to process
|
||||
progress++;
|
||||
useEnergy();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, true));
|
||||
setChanged(level, pos, blockState);
|
||||
|
||||
if (hasCraftingFinished()) {
|
||||
outputBlastingResult(INPUT_SLOT, OUTPUT_SLOT);
|
||||
resetProgress();
|
||||
}
|
||||
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
||||
// Recipe detected but we ran out of power
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
progress = progress > 0 ? progress - 1 : 0;
|
||||
} else {
|
||||
// Invalid recipe
|
||||
resetProgress();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
}
|
||||
} else {
|
||||
// Secondary slot is NOT empty, try alloying recipes
|
||||
if (hasAlloyingRecipe(INPUT_SLOT, SECONDARY_INPUT_SLOT)) {
|
||||
if (hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
||||
// Alloy recipe detected! We have enough energy to process
|
||||
progress++;
|
||||
useEnergy();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, true));
|
||||
setChanged(level, pos, blockState);
|
||||
|
||||
if (hasCraftingFinished()) {
|
||||
outputAlloyingResult(INPUT_SLOT, SECONDARY_INPUT_SLOT, OUTPUT_SLOT);
|
||||
resetProgress();
|
||||
}
|
||||
} else {
|
||||
// Recipe detected but we ran out of power
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
progress = progress > 0 ? progress - 1 : 0;
|
||||
}
|
||||
} else {
|
||||
// Invalid recipe
|
||||
resetProgress();
|
||||
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||
setChanged(level, pos, blockState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void chargeFromItem() {
|
||||
ItemStack stack;
|
||||
|
||||
try {
|
||||
stack = inventory.getStackInSlot(ENERGY_SLOT);
|
||||
|
||||
if (stack.isEmpty()) return;
|
||||
|
||||
IEnergyStorage itemEnergy = stack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
if (itemEnergy == null || !itemEnergy.canExtract()) return;
|
||||
|
||||
int freeCapacity = ENERGY_STORAGE.getMaxEnergyStored() - ENERGY_STORAGE.getEnergyStored();
|
||||
if (freeCapacity <= 0) return;
|
||||
|
||||
int maxMove = Math.min(MAX_TRANSFER, freeCapacity);
|
||||
|
||||
// Simulate extraction first
|
||||
int canExtract = itemEnergy.extractEnergy(maxMove, true);
|
||||
if (canExtract <= 0) return;
|
||||
|
||||
// Receive into block (simulate then execute is safest)
|
||||
int canReceive = ENERGY_STORAGE.receiveEnergy(canExtract, true);
|
||||
if (canReceive <= 0) return;
|
||||
|
||||
int extracted = itemEnergy.extractEnergy(canReceive, false);
|
||||
ENERGY_STORAGE.receiveEnergy(maxMove, false);
|
||||
|
||||
setChanged();
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void outputBlastingResult(int slot, int resultSlot) {
|
||||
Optional<RecipeHolder<BlastingRecipe>> recipe = getFurnaceRecipe(inventory.getStackInSlot(slot));
|
||||
ItemStack output = recipe.get().value().getResultItem(null);
|
||||
|
||||
// 2x multiplier for smelting recipes
|
||||
|
||||
inventory.extractItem(slot, 1, false);
|
||||
inventory.setStackInSlot(resultSlot, new ItemStack(output.getItem(),
|
||||
inventory.getStackInSlot(resultSlot).getCount() + (output.getCount() * 2)));
|
||||
}
|
||||
|
||||
private void outputAlloyingResult(int inputSlot, int secondaryInputSlot, int outputSlot) {
|
||||
Optional<RecipeHolder<ElectricArcFurnaceRecipe>> recipe = getAlloyingRecipe(inventory.getStackInSlot(inputSlot), inventory.getStackInSlot(secondaryInputSlot));
|
||||
ItemStack output = recipe.get().value().getResultItem(null);
|
||||
|
||||
inventory.extractItem(inputSlot, recipe.get().value().baseCount(), false);
|
||||
inventory.extractItem(secondaryInputSlot, recipe.get().value().alloyCount(), false);
|
||||
inventory.setStackInSlot(outputSlot, new ItemStack(output.getItem(), inventory.getStackInSlot(outputSlot).getCount() + (output.getCount())));
|
||||
}
|
||||
|
||||
private void resetProgress() {
|
||||
this.progress = 0;
|
||||
this.maxProgress = DEFAULT_MAX_PROGRESS;
|
||||
}
|
||||
|
||||
private void useEnergy() {
|
||||
this.ENERGY_STORAGE.extractEnergy(MACHINE_ENERGY_COST, false);
|
||||
}
|
||||
|
||||
private boolean hasEnoughEnergyToCraft(int energyCost) {
|
||||
return ENERGY_STORAGE.getEnergyStored() >= energyCost;
|
||||
}
|
||||
|
||||
private boolean canInsertItemIntoOutputSlot(ItemStack output, int slot) {
|
||||
return inventory.getStackInSlot(slot).isEmpty() ||
|
||||
inventory.getStackInSlot(slot).getItem() == output.getItem();
|
||||
}
|
||||
|
||||
private boolean canInsertAmountIntoOutputSlot(int count, int slot) {
|
||||
int maxCount = inventory.getStackInSlot(slot).isEmpty() ? 64 : inventory.getStackInSlot(slot).getMaxStackSize();
|
||||
int currentCount = inventory.getStackInSlot(slot).getCount();
|
||||
|
||||
return maxCount >= currentCount + count;
|
||||
}
|
||||
|
||||
private boolean isOutputSlotEmptyOrReceivable(int slot) {
|
||||
return this.inventory.getStackInSlot(slot).isEmpty() ||
|
||||
this.inventory.getStackInSlot(slot).getCount() < this.inventory.getStackInSlot(slot).getMaxStackSize();
|
||||
}
|
||||
|
||||
private boolean hasCraftingFinished() {
|
||||
maxProgress = DEFAULT_MAX_PROGRESS;
|
||||
return this.progress >= this.maxProgress;
|
||||
}
|
||||
|
||||
|
||||
private boolean hasAlloyingRecipe(int slotBase, int slotAlloy) {
|
||||
ItemStack baseStack = inventory.getStackInSlot(slotBase);
|
||||
ItemStack alloyStack = inventory.getStackInSlot(slotAlloy);
|
||||
|
||||
Optional<RecipeHolder<ElectricArcFurnaceRecipe>> opt =
|
||||
getAlloyingRecipe(baseStack, alloyStack);
|
||||
|
||||
if (opt.isEmpty()) return false;
|
||||
|
||||
ElectricArcFurnaceRecipe recipe = opt.get().value();
|
||||
|
||||
// 1) Check required input counts
|
||||
if (baseStack.getCount() < recipe.baseCount()) return false;
|
||||
if (alloyStack.getCount() < recipe.alloyCount()) return false;
|
||||
|
||||
// 2) Check output slot compatibility + space
|
||||
ItemStack output = recipe.getResultItem(null);
|
||||
|
||||
maxProgress = recipe.cookTime();
|
||||
|
||||
return canInsertItemIntoOutputSlot(output, OUTPUT_SLOT)
|
||||
&& canInsertAmountIntoOutputSlot(output.getCount(), OUTPUT_SLOT);
|
||||
}
|
||||
|
||||
private Optional<RecipeHolder<ElectricArcFurnaceRecipe>> getAlloyingRecipe(ItemStack base, ItemStack alloy) {
|
||||
if (base.isEmpty()) return Optional.empty();
|
||||
if (alloy.isEmpty()) return Optional.empty();
|
||||
|
||||
return this.level.getRecipeManager()
|
||||
.getRecipeFor(
|
||||
ModRecipes.ELECTRIC_ARC_FURNACE_RECIPE_TYPE.get(),
|
||||
new ElectricArcFurnaceRecipeInput(base, alloy),
|
||||
level
|
||||
);
|
||||
}
|
||||
|
||||
private boolean hasFurnaceRecipe(int slot) {
|
||||
Optional<RecipeHolder<BlastingRecipe>> recipe = getFurnaceRecipe(new ItemStack(inventory.getStackInSlot(slot).getItem().asItem(), 1));
|
||||
if (recipe.isEmpty())
|
||||
return false;
|
||||
|
||||
ItemStack output = recipe.get().value().getResultItem(null);
|
||||
return canInsertAmountIntoOutputSlot(output.getCount() * 2, OUTPUT_SLOT) && canInsertItemIntoOutputSlot(output, OUTPUT_SLOT);
|
||||
}
|
||||
|
||||
private Optional<RecipeHolder<BlastingRecipe>> getFurnaceRecipe(ItemStack stack) {
|
||||
if (stack.isEmpty()) return Optional.empty();
|
||||
|
||||
return this.level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, new SingleRecipeInput(stack), level);
|
||||
|
||||
}
|
||||
|
||||
public void sendUpdate() {
|
||||
setChanged();
|
||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
|
||||
private final IItemHandler fullHandler = new SidedSlotHandler(inventory, new int[]{INPUT_SLOT, SECONDARY_INPUT_SLOT, OUTPUT_SLOT, ENERGY_SLOT}, true, true);
|
||||
private final IItemHandler emptyJeiHandler = new SidedSlotHandler(inventory, new int[]{}, false, false);
|
||||
private final IItemHandler inputHandler = new SidedSlotHandler(inventory, new int[]{0,1}, true, true);
|
||||
private final IItemHandler outputHandler = new SidedSlotHandler(inventory, new int[]{2,3}, false, true);
|
||||
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
|
||||
|
||||
public IItemHandler getItemHandler(Direction direction) {
|
||||
if (direction != null)
|
||||
return isFormed() ? fullHandler : null;
|
||||
return isFormed() ? fullHandler : emptyJeiHandler;
|
||||
}
|
||||
|
||||
public IEnergyStorage getEnergyStorage(@Nullable Direction direction) {
|
||||
if (direction == null)
|
||||
return isFormed() ? ENERGY_STORAGE : NULL_ENERGY_STORAGE;
|
||||
return isFormed() ? ENERGY_STORAGE : null;
|
||||
}
|
||||
|
||||
public IEnergyStorage getTrueEnergyStorage(@Nullable Direction direction) {
|
||||
return this.ENERGY_STORAGE;
|
||||
}
|
||||
|
||||
private final ModEnergyStorage ENERGY_STORAGE = createEnergyStorage(ENERGY_CAPACITY, MAX_TRANSFER);
|
||||
private final ModEnergyStorage NULL_ENERGY_STORAGE = createEnergyStorage(0, 0);
|
||||
|
||||
private ModEnergyStorage createEnergyStorage(int capacity, int transfer) {
|
||||
return new ModEnergyStorage(capacity, transfer) {
|
||||
@Override
|
||||
public void onEnergyChanged() {
|
||||
setChanged();
|
||||
getLevel().sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ItemStackHandler getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public void drops() {
|
||||
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
|
||||
for(int i = 0; i < inventory.getSlots(); i++) {
|
||||
inv.setItem(i, inventory.getStackInSlot(i));
|
||||
}
|
||||
|
||||
Containers.dropContents(this.level, this.worldPosition, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider pRegistries) {
|
||||
tag.put("inventory", inventory.serializeNBT(pRegistries));
|
||||
tag.putInt("electric_arc_furnace.progress", progress);
|
||||
tag.putInt("electric_arc_furnace.maxProgress", maxProgress);
|
||||
tag.putInt("electric_arc_furnace.energy", ENERGY_STORAGE.getEnergyStored());
|
||||
super.saveAdditional(tag, pRegistries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider pRegistries) {
|
||||
super.loadAdditional(tag, pRegistries);
|
||||
inventory.deserializeNBT(pRegistries, tag.getCompound("inventory"));
|
||||
progress = tag.getInt("electric_arc_furnace.progress");
|
||||
maxProgress = tag.getInt("electric_arc_furnace.maxProgress");
|
||||
ENERGY_STORAGE.setEnergy(tag.getInt("electric_arc_furnace.energy"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
if (isFormed())
|
||||
return new VacuumArcFurnaceMenu(i, inventory, this, this.data);
|
||||
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Packet<ClientGamePacketListener> getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider pRegistries) {
|
||||
return saveWithoutMetadata(pRegistries);
|
||||
}
|
||||
|
||||
private static BlockPos rotateY(BlockPos off, Direction facing) {
|
||||
// Assumes "default" shape faces NORTH.
|
||||
return switch (facing) {
|
||||
case NORTH -> off;
|
||||
case EAST -> new BlockPos(-off.getZ(), off.getY(), off.getX());
|
||||
case SOUTH -> new BlockPos(-off.getX(), off.getY(), -off.getZ());
|
||||
case WEST -> new BlockPos(off.getZ(), off.getY(), -off.getX());
|
||||
default -> off;
|
||||
};
|
||||
}
|
||||
|
||||
public static final MultiblockHelper.ShapePart[] SHAPE = new MultiblockHelper.ShapePart[] {
|
||||
|
||||
//Layer -1
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,-1,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,-1,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,-1,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,-1,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,-1,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,-1,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,-1,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,-1,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,-1,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
|
||||
//Layer 0
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,0,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,0,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,0,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,0,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,0,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,0,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,0,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,0,1), s -> s.is(Blocks.AIR)),
|
||||
|
||||
//Layer 1
|
||||
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,1,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,1,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(1,1,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,1,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,1,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(-1,1,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,1,0), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,1,1), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
new MultiblockHelper.ShapePart(new BlockPos(0,1,2), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||
// new MultiblockHelper.ShapePart(new BlockPos(-1,0,0), s -> s.is(Blocks.AMETHYST_BLOCK))
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// MULTIBLOCK
|
||||
/// LOGIC
|
||||
/// BELOW
|
||||
|
||||
|
||||
// record ShapePart (BlockPos offset, Predicate<BlockState> rule) {}
|
||||
|
||||
private boolean formed = false; // cached runtime state
|
||||
|
||||
// Assumes the default state is NORTH.
|
||||
|
||||
// (Left -Right, Up -Down, Back -Front)
|
||||
|
||||
|
||||
// private static final BlockPos[] SHAPE = new BlockPos[] {
|
||||
// new BlockPos(1, 0, 0),
|
||||
// new BlockPos(0, 0, 1),
|
||||
// new BlockPos(1, 0, 1),
|
||||
//
|
||||
// new BlockPos(0, 1, 0),
|
||||
// new BlockPos(1, 1, 0),
|
||||
// new BlockPos(0, 1, 1),
|
||||
// new BlockPos(1, 1, 1),
|
||||
// };
|
||||
|
||||
|
||||
|
||||
public boolean isFormed() {
|
||||
return getBlockState().hasProperty(AphelionBlockStateProperties.FORMED)
|
||||
&& getBlockState().getValue(AphelionBlockStateProperties.FORMED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFormed(boolean formed) {
|
||||
this.formed = formed;
|
||||
invalidateCapabilities();
|
||||
if (!formed) {
|
||||
drops();
|
||||
}
|
||||
}
|
||||
|
||||
private void setFormedState(boolean value) {
|
||||
BlockState state = getBlockState();
|
||||
if (state.hasProperty(ElectricArcFurnace.FORMED) && state.getValue(ElectricArcFurnace.FORMED) != value) {
|
||||
level.setBlock(worldPosition, state.setValue(ElectricArcFurnace.FORMED, value), 3);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user