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:
@@ -1,6 +1,7 @@
|
||||
// 1.21.1 2026-01-17T20:45:45.6230298 Loot Tables
|
||||
// 1.21.1 2026-01-18T19:51:57.3558369 Loot Tables
|
||||
69d8318ddba171526d1fabb87d9d93548ed8598e data/aphelion/loot_table/blocks/arc_furnace_casing.json
|
||||
05f08985e601d30116f67e2f07b48b03b40cdca6 data/aphelion/loot_table/blocks/block_steel.json
|
||||
ff43a9c3741faf10b1e156a7a74d5cfb035cc118 data/aphelion/loot_table/blocks/dimension_changer.json
|
||||
b63130d9c10485676303d729807b6fcaac080294 data/aphelion/loot_table/blocks/electric_arc_furnace.json
|
||||
1ab50c99e9f478840b9d003fd56ebdcab12fbbce data/aphelion/loot_table/blocks/test_block.json
|
||||
7d8eeb99a1bc942a6e2cf292b21fd4534062b5ab data/aphelion/loot_table/blocks/vacuum_arc_furnace_controller.json
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
// 1.21.1 2026-01-17T21:22:18.4335623 Block States: aphelion
|
||||
// 1.21.1 2026-01-18T19:51:57.3548439 Block States: aphelion
|
||||
851ff42f7b21dec86107c8e0cefb3934ae4ebc08 assets/aphelion/blockstates/block_steel.json
|
||||
30b9c0efd7aaadb5412d98e4568f98b3632adbb9 assets/aphelion/blockstates/dimension_changer.json
|
||||
cb4287104006c80c8396b290ab5258df65d62cef assets/aphelion/blockstates/electric_arc_furnace.json
|
||||
b86c50fddcf6c8c6c19cb748529239d5962a3ede assets/aphelion/blockstates/test_block.json
|
||||
a810b97f4dace35d026f28d96cb9c47c93600d75 assets/aphelion/models/block/block_steel.json
|
||||
2d3592b7ab7132908709243e97540151e0fb762e assets/aphelion/models/block/dimension_changer.json
|
||||
5f7e8674070f31a63875b5d6147153bfa0eef61a assets/aphelion/models/block/electric_arc_furnace.json
|
||||
e0971228b4a1c4bc9dbab58a7dacdc3ae6037e02 assets/aphelion/models/block/test_block.json
|
||||
cdc831b0f1c462be64825fd34bd446e5b95afac6 assets/aphelion/models/item/arc_furnace_casing.json
|
||||
3599f9037eb2f66de1765318b97ab564c3eae92f assets/aphelion/models/item/block_steel.json
|
||||
db0ec473a016ce05c258cde18a217d47a9ea8324 assets/aphelion/models/item/dimension_changer.json
|
||||
279080c06ada87f54fd0a7b885b256dbe25a946a assets/aphelion/models/item/electric_arc_furnace.json
|
||||
74418ef1cf678e72e7534924274688ef5a68af0e assets/aphelion/models/item/test_block.json
|
||||
88ca3602517e99f7feaed57eddfc96965a25761c assets/aphelion/models/item/vacuum_arc_furnace_controller.json
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.xevianlight.aphelion.recipe.ModRecipes;
|
||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceScreen;
|
||||
import net.xevianlight.aphelion.screen.ModMenuTypes;
|
||||
import net.xevianlight.aphelion.screen.TestBlockScreen;
|
||||
import net.xevianlight.aphelion.screen.VacuumArcFurnaceScreen;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
@@ -120,6 +121,7 @@ public class Aphelion {
|
||||
public static void registerScreens(RegisterMenuScreensEvent event) {
|
||||
event.register(ModMenuTypes.TEST_BLOCK_MENU.get(), TestBlockScreen::new);
|
||||
event.register(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), ElectricArcFurnaceScreen::new);
|
||||
event.register(ModMenuTypes.VACUUM_ARC_FURNACE_MENU.get(), VacuumArcFurnaceScreen::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,10 +4,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.block.entity.custom.DimensionChangerBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.EAFPartEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.*;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -33,4 +30,9 @@ public class ModBlockEntities {
|
||||
BLOCK_ENTITIES.register("eaf_part_entity", () -> BlockEntityType.Builder.of(
|
||||
EAFPartEntity::new, ModBlocks.ARC_FURNACE_CASING_BLOCK.get()).build(null)
|
||||
);
|
||||
|
||||
public static final Supplier<BlockEntityType<VacuumArcFurnaceControllerEntity>> VACUUM_ARC_FURNACE_ENTITY =
|
||||
BLOCK_ENTITIES.register("vacuum_arc_furnace_controller_entity", () -> BlockEntityType.Builder.of(
|
||||
VacuumArcFurnaceControllerEntity::new, ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get()).build(null)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,4 +14,5 @@ public class ModBlocks {
|
||||
public static final DeferredBlock<Block> DIMENSION_CHANGER = BLOCKS.register("dimension_changer", () -> new DimensionChangerBlock(DimensionChangerBlock.getProperties()));
|
||||
public static final DeferredBlock<Block> ELECTRIC_ARC_FURNACE = BLOCKS.register("electric_arc_furnace", () -> new ElectricArcFurnace(ElectricArcFurnace.getProperties()));
|
||||
public static final DeferredBlock<Block> ARC_FURNACE_CASING_BLOCK = BLOCKS.register("arc_furnace_casing", () -> new ArcFurnaceCasingBlock(ArcFurnaceCasingBlock.getProperties()));
|
||||
public static final DeferredBlock<Block> VACUUM_ARC_FURNACE_CONTROLLER = BLOCKS.register("vacuum_arc_furnace_controller", () -> new VacuumArcFurnaceController(VacuumArcFurnaceController.getProperties()));
|
||||
}
|
||||
|
||||
@@ -33,4 +33,5 @@ public static final DeferredItem<Item> MUSIC_DISC_BIT_SHIFT = ITEMS.register("mu
|
||||
public static final DeferredItem<BlockItem> ELECTRIC_ARC_FURNACE = ITEMS.register("electric_arc_furnace", () -> new BlockItem(ModBlocks.ELECTRIC_ARC_FURNACE.get(), ElectricArcFurnace.getItemProperties()));
|
||||
public static final DeferredItem<BlockItem> BLOCK_STEEL = ITEMS.register("block_steel", () -> new BlockItem(ModBlocks.BLOCK_STEEL.get(), BlockSteel.getItemProperties()));
|
||||
public static final DeferredItem<BlockItem> ARC_FURNACE_CASING_BLOCK = ITEMS.register("arc_furnace_casing", () -> new BlockItem(ModBlocks.ARC_FURNACE_CASING_BLOCK.get(), ArcFurnaceCasingBlock.getItemProperties()));
|
||||
public static final DeferredItem<BlockItem> VACUUM_ARC_FURNACE_CONTROLLER = ITEMS.register("vacuum_arc_furnace_controller", () -> new BlockItem(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get(), VacuumArcFurnaceController.getItemProperties()));
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class ModBlockLootTableProvider extends BlockLootSubProvider {
|
||||
dropSelf(ModBlocks.DIMENSION_CHANGER.get());
|
||||
dropSelf(ModBlocks.ELECTRIC_ARC_FURNACE.get());
|
||||
dropSelf(ModBlocks.ARC_FURNACE_CASING_BLOCK.get());
|
||||
dropSelf(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,11 +18,12 @@ public class ModBlockStateProvider extends BlockStateProvider {
|
||||
protected void registerStatesAndModels() {
|
||||
blockWithItem(ModBlocks.TEST_BLOCK);
|
||||
|
||||
// horizontalBlock(ModBlocks.ELECTRIC_ARC_FURNACE.get(), models().orientable("aphelion:electric_arc_furnace",
|
||||
// mcLoc("block/blast_furnace_side"),
|
||||
// modLoc("block/electric_arc_furnace_front"),
|
||||
// mcLoc("block/blast_furnace_top")));
|
||||
horizontalBlock(ModBlocks.ELECTRIC_ARC_FURNACE.get(), models().orientable("aphelion:electric_arc_furnace",
|
||||
mcLoc("block/blast_furnace_side"),
|
||||
modLoc("block/electric_arc_furnace_front"),
|
||||
mcLoc("block/blast_furnace_top")));
|
||||
blockItem(ModBlocks.ELECTRIC_ARC_FURNACE);
|
||||
blockItem(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER);
|
||||
|
||||
blockWithItem(ModBlocks.BLOCK_STEEL);
|
||||
blockWithItem(ModBlocks.DIMENSION_CHANGER);
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.neoforged.neoforge.network.registration.PayloadRegistrar;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.network.ServerPayloadHandler;
|
||||
import net.xevianlight.aphelion.network.packet.PartitionData;
|
||||
@@ -22,6 +23,8 @@ public class ModBusEvents {
|
||||
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.TEST_BLOCK_ENTITY.get(), TestBlockEntity::getItemHandler);
|
||||
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), ElectricArcFurnaceEntity::getItemHandler);
|
||||
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), ElectricArcFurnaceEntity::getEnergyStorage);
|
||||
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.VACUUM_ARC_FURNACE_ENTITY.get(), VacuumArcFurnaceControllerEntity::getItemHandler);
|
||||
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.VACUUM_ARC_FURNACE_ENTITY.get(), VacuumArcFurnaceControllerEntity::getEnergyStorage);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package net.xevianlight.aphelion.screen;
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
@@ -14,7 +11,6 @@ import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.neoforged.neoforge.items.SlotItemHandler;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.util.EnergyItemSlot;
|
||||
import net.xevianlight.aphelion.util.ExtractOnlySlot;
|
||||
|
||||
@@ -62,8 +62,8 @@ public class ElectricArcFurnaceScreen extends AbstractContainerScreen<ElectricAr
|
||||
}
|
||||
|
||||
private void renderEnergyBar(GuiGraphics guiGraphics, int x, int y) {
|
||||
int stored = menu.blockEntity.getEnergyStorage(null).getEnergyStored();
|
||||
int max = menu.blockEntity.getEnergyStorage(null).getMaxEnergyStored();
|
||||
int stored = menu.blockEntity.getTrueEnergyStorage(null).getEnergyStored();
|
||||
int max = menu.blockEntity.getTrueEnergyStorage(null).getMaxEnergyStored();
|
||||
|
||||
int h = (max <= 0) ? 0 : (int) Math.round((stored / (double) max) * 42.0);
|
||||
h = Math.max(0, Math.min(42, h));
|
||||
@@ -79,7 +79,7 @@ public class ElectricArcFurnaceScreen extends AbstractContainerScreen<ElectricAr
|
||||
|
||||
private void assignEnergyInfoArea() {
|
||||
energyInfoArea = new EnergyDisplayTooltipArea(((width - imageWidth) / 2) + 9,
|
||||
((height - imageHeight) / 2 ) + 9, menu.blockEntity.getEnergyStorage(null), 14, 42);
|
||||
((height - imageHeight) / 2 ) + 9, menu.blockEntity.getTrueEnergyStorage(null), 14, 42);
|
||||
}
|
||||
|
||||
private void renderEnergyAreaTooltip(GuiGraphics guiGraphics, int pMouseX, int pMouseY, int x, int y) {
|
||||
|
||||
@@ -16,9 +16,13 @@ public class ModMenuTypes {
|
||||
|
||||
public static DeferredHolder<MenuType<?>,MenuType<TestBlockMenu>> TEST_BLOCK_MENU =
|
||||
registerMenuType("test_block_menu", TestBlockMenu::new);
|
||||
|
||||
public static DeferredHolder<MenuType<?>,MenuType<ElectricArcFurnaceMenu>> ELECTRIC_ARC_FURNACE_MENU =
|
||||
registerMenuType("electric_arc_furnace_menu", ElectricArcFurnaceMenu::new);
|
||||
|
||||
public static DeferredHolder<MenuType<?>,MenuType<VacuumArcFurnaceMenu>> VACUUM_ARC_FURNACE_MENU =
|
||||
registerMenuType("vacuum_arc_furnace_menu", VacuumArcFurnaceMenu::new);
|
||||
|
||||
private static <T extends AbstractContainerMenu>DeferredHolder<MenuType<?>, MenuType<T>> registerMenuType(String name,
|
||||
IContainerFactory<T> factory) {
|
||||
return MENUS.register(name, () -> IMenuTypeExtension.create(factory));
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package net.xevianlight.aphelion.screen;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
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.inventory.SimpleContainerData;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.neoforged.neoforge.items.SlotItemHandler;
|
||||
import net.xevianlight.aphelion.block.custom.VacuumArcFurnaceController;
|
||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
||||
import net.xevianlight.aphelion.util.EnergyItemSlot;
|
||||
import net.xevianlight.aphelion.util.ExtractOnlySlot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class VacuumArcFurnaceMenu extends AbstractContainerMenu {
|
||||
|
||||
public final VacuumArcFurnaceControllerEntity blockEntity;
|
||||
private final Level level;
|
||||
private final ContainerData data;
|
||||
|
||||
public VacuumArcFurnaceMenu(int i, Inventory inventory, FriendlyByteBuf extraData) {
|
||||
this(i, inventory, inventory.player.level().getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(4));
|
||||
}
|
||||
|
||||
public VacuumArcFurnaceMenu(int i, Inventory inventory, BlockEntity blockEntity, ContainerData data) {
|
||||
super(ModMenuTypes.VACUUM_ARC_FURNACE_MENU.get(), i);
|
||||
this.blockEntity = ((VacuumArcFurnaceControllerEntity) blockEntity);
|
||||
this.level = inventory.player.level();
|
||||
this.data = data;
|
||||
|
||||
addPlayerInventory(inventory);
|
||||
addPlayerHotbar(inventory);
|
||||
|
||||
this.addSlot(new EnergyItemSlot(this.blockEntity.inventory, VacuumArcFurnaceControllerEntity.ENERGY_SLOT, 8, 54));
|
||||
this.addSlot(new SlotItemHandler(this.blockEntity.inventory, VacuumArcFurnaceControllerEntity.INPUT_SLOT, 63, 35));
|
||||
this.addSlot(new SlotItemHandler(this.blockEntity.inventory, VacuumArcFurnaceControllerEntity.SECONDARY_INPUT_SLOT, 40, 35));
|
||||
this.addSlot(new ExtractOnlySlot(this.blockEntity.inventory, VacuumArcFurnaceControllerEntity.OUTPUT_SLOT, 125, 35));
|
||||
|
||||
addDataSlots(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
|
||||
// must assign a slot number to each of the slots used by the GUI.
|
||||
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
|
||||
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
|
||||
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
|
||||
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
|
||||
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
|
||||
private static final int HOTBAR_SLOT_COUNT = 9;
|
||||
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
|
||||
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
|
||||
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
|
||||
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
|
||||
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
|
||||
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
|
||||
|
||||
// THIS YOU HAVE TO DEFINE!
|
||||
private static final int TE_INVENTORY_SLOT_COUNT = 3; // must be the number of slots you have!
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(Player playerIn, int pIndex) {
|
||||
Slot sourceSlot = slots.get(pIndex);
|
||||
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
|
||||
ItemStack sourceStack = sourceSlot.getItem();
|
||||
ItemStack copyOfSourceStack = sourceStack.copy();
|
||||
|
||||
// Check if the slot clicked is one of the vanilla container slots
|
||||
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
|
||||
// This is a vanilla container slot so merge the stack into the tile inventory
|
||||
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
|
||||
+ TE_INVENTORY_SLOT_COUNT, false)) {
|
||||
blockEntity.sendUpdate();
|
||||
return ItemStack.EMPTY; // EMPTY_ITEM
|
||||
}
|
||||
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
|
||||
// This is a TE slot so merge the stack into the players inventory
|
||||
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
|
||||
blockEntity.sendUpdate();
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else {
|
||||
System.out.println("Invalid slotIndex:" + pIndex);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
// If stack size == 0 (the entire stack was moved) set slot contents to null
|
||||
if (sourceStack.getCount() == 0) {
|
||||
sourceSlot.set(ItemStack.EMPTY);
|
||||
blockEntity.sendUpdate();
|
||||
} else {
|
||||
blockEntity.sendUpdate();
|
||||
sourceSlot.setChanged();
|
||||
}
|
||||
sourceSlot.onTake(playerIn, sourceStack);
|
||||
blockEntity.sendUpdate();
|
||||
return copyOfSourceStack;
|
||||
}
|
||||
|
||||
public int getScaledArrowProgress() {
|
||||
int progress = this.data.get(0);
|
||||
int maxProgress = this.data.get(1);
|
||||
int arrowPixelSize = 24;
|
||||
|
||||
return maxProgress != 0 && progress != 0 ? progress * arrowPixelSize / maxProgress : 0;
|
||||
}
|
||||
|
||||
private void addPlayerInventory(Inventory playerInventory) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int l = 0; l < 9; ++l) {
|
||||
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPlayerHotbar(Inventory playerInventory) {
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package net.xevianlight.aphelion.screen;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.screen.renderer.EnergyDisplayTooltipArea;
|
||||
import net.xevianlight.aphelion.util.MouseUtil;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class VacuumArcFurnaceScreen extends AbstractContainerScreen<VacuumArcFurnaceMenu> {
|
||||
|
||||
private static final ResourceLocation GUI_TEXTURE =
|
||||
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "textures/gui/vacuum_arc_furnace/gui.png");
|
||||
private static final ResourceLocation ARROW_TEXTURE =
|
||||
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID,"textures/gui/base/arrow_progress.png");
|
||||
|
||||
private EnergyDisplayTooltipArea energyInfoArea;
|
||||
|
||||
public VacuumArcFurnaceScreen(VacuumArcFurnaceMenu menu, Inventory playerInventory, Component title) {
|
||||
super(menu, playerInventory, title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
// Gets rid of labels
|
||||
this.inventoryLabelY = 73;
|
||||
this.titleLabelY = 5;
|
||||
this.titleLabelX = 35;
|
||||
|
||||
assignEnergyInfoArea();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
|
||||
int x = (width - imageWidth) / 2;
|
||||
int y = (height - imageHeight) / 2;
|
||||
|
||||
guiGraphics.blit(GUI_TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
|
||||
|
||||
renderProgressArrow(guiGraphics, x, y);
|
||||
if (menu.blockEntity.getBlockState().getValue(BlockStateProperties.LIT)) {
|
||||
guiGraphics.blit(GUI_TEXTURE, x + 54, y + 14, 176, 75, 13, 18);
|
||||
}
|
||||
|
||||
renderEnergyBar(guiGraphics, x , y);
|
||||
}
|
||||
|
||||
private void renderProgressArrow(GuiGraphics guiGraphics, int x, int y) {
|
||||
guiGraphics.blit(ARROW_TEXTURE,x + 88, y + 35, 0, 0, menu.getScaledArrowProgress(), 16, 24, 16);
|
||||
}
|
||||
|
||||
private void renderEnergyBar(GuiGraphics guiGraphics, int x, int y) {
|
||||
int stored = menu.blockEntity.getTrueEnergyStorage(null).getEnergyStored();
|
||||
int max = menu.blockEntity.getTrueEnergyStorage(null).getMaxEnergyStored();
|
||||
|
||||
int h = (max <= 0) ? 0 : (int) Math.round((stored / (double) max) * 42.0);
|
||||
h = Math.max(0, Math.min(42, h));
|
||||
int w = 14;
|
||||
|
||||
int drawX = x + 9;
|
||||
int drawY = y + 9 + (42 - h); // move up as it fills
|
||||
int u = 176;
|
||||
int v = 15 + (42 - h); // sample lower part of bar texture
|
||||
|
||||
guiGraphics.blit(GUI_TEXTURE, drawX, drawY, u, v, w, h);
|
||||
}
|
||||
|
||||
private void assignEnergyInfoArea() {
|
||||
energyInfoArea = new EnergyDisplayTooltipArea(((width - imageWidth) / 2) + 9,
|
||||
((height - imageHeight) / 2 ) + 9, menu.blockEntity.getTrueEnergyStorage(null), 14, 42);
|
||||
}
|
||||
|
||||
private void renderEnergyAreaTooltip(GuiGraphics guiGraphics, int pMouseX, int pMouseY, int x, int y) {
|
||||
if(isMouseAboveArea(pMouseX, pMouseY, x, y, 9, 9, 14, 42)) {
|
||||
guiGraphics.renderTooltip(this.font, energyInfoArea.getTooltips(),
|
||||
Optional.empty(), pMouseX - x, pMouseY - y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
|
||||
renderBackground(guiGraphics, mouseX, mouseY, delta);
|
||||
super.render(guiGraphics, mouseX, mouseY, delta);
|
||||
renderTooltip(guiGraphics, mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
super.renderLabels(guiGraphics, mouseX, mouseY);
|
||||
int x = (width - imageWidth) / 2;
|
||||
int y = (height - imageHeight) / 2;
|
||||
|
||||
renderEnergyAreaTooltip(guiGraphics, mouseX, mouseY, x, y);
|
||||
}
|
||||
|
||||
public static boolean isMouseAboveArea(int pMouseX, int pMouseY, int x, int y, int offsetX, int offsetY, int width, int height) {
|
||||
return MouseUtil.isMouseOver(pMouseX, pMouseY, x + offsetX, y + offsetY, width, height);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.xevianlight.aphelion.util;
|
||||
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
|
||||
public class AphelionBlockStateProperties extends BlockStateProperties {
|
||||
public static final BooleanProperty FORMED = BooleanProperty.create("formed");
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.xevianlight.aphelion.util;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface IMultiblockController {
|
||||
boolean isFormed();
|
||||
void setFormed(boolean formed);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.xevianlight.aphelion.util;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface IMultiblockPart {
|
||||
@Nullable BlockPos getControllerPos();
|
||||
|
||||
void setControllerPos(@Nullable BlockPos pos);
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package net.xevianlight.aphelion.util;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
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.level.block.state.properties.BooleanProperty;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class MultiblockHelper {
|
||||
|
||||
public record ShapePart (BlockPos offset, Predicate<BlockState> rule) {}
|
||||
|
||||
public static List<BlockPos> getPartPositions(BlockState state, BlockPos pos, ShapePart[] shape) {
|
||||
Direction facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
|
||||
List<BlockPos> out = new ArrayList<>(shape.length);
|
||||
|
||||
for (ShapePart part : shape) {
|
||||
BlockPos rotate = rotateY(part.offset, facing);
|
||||
out.add(pos.offset(rotate));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private static BlockPos rotateY(BlockPos offset, Direction facing) {
|
||||
// Assumes default shape faces north
|
||||
|
||||
return switch (facing) {
|
||||
case NORTH -> offset;
|
||||
case EAST -> new BlockPos(-offset.getZ(), offset.getY(), offset.getX());
|
||||
case SOUTH -> new BlockPos(-offset.getX(), offset.getY(), -offset.getZ());
|
||||
case WEST -> new BlockPos(offset.getZ(), offset.getY(), -offset.getX());
|
||||
default -> offset;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean structureMatches(Level level, BlockState state, BlockPos pos, ShapePart[] shape) {
|
||||
if (level == null || level.isClientSide) return false;
|
||||
|
||||
Direction facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
|
||||
for (ShapePart part : shape) {
|
||||
BlockPos testPos = pos.offset(rotateY(part.offset(), facing));
|
||||
BlockState check = level.getBlockState(testPos);
|
||||
|
||||
if (!part.rule().test(check)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void tryForm(Level level, BlockState state, BlockPos pos, ShapePart[] shape, @Nullable BooleanProperty formedProp) {
|
||||
if (level == null || level.isClientSide) return;
|
||||
|
||||
structureMatchesDebug(level, state, pos, shape);
|
||||
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (!(be instanceof IMultiblockController controller)) return;
|
||||
|
||||
boolean valid = structureMatches(level, state, pos, shape);
|
||||
|
||||
if (valid && !controller.isFormed()) {
|
||||
controller.setFormed(true);
|
||||
linkParts(level, state, pos, shape, formedProp);
|
||||
if (state.hasProperty(AphelionBlockStateProperties.FORMED) && !state.getValue(AphelionBlockStateProperties.FORMED)) {
|
||||
level.setBlock(pos, state.setValue(AphelionBlockStateProperties.FORMED, true), 3);
|
||||
}
|
||||
} else if (!valid && controller.isFormed()) {
|
||||
unform(level, state, pos, shape, formedProp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void unform(Level level, BlockState state, BlockPos pos, ShapePart[] shape, @Nullable BooleanProperty formedProp) {
|
||||
if (level == null || level.isClientSide) return;
|
||||
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (!(be instanceof IMultiblockController controller)) return;
|
||||
|
||||
controller.setFormed(false);
|
||||
if (state.hasProperty(AphelionBlockStateProperties.FORMED) && state.getValue(AphelionBlockStateProperties.FORMED)) {
|
||||
level.setBlock(pos, state.setValue(AphelionBlockStateProperties.FORMED, false), 3);
|
||||
}
|
||||
|
||||
unlinkParts(level, state, pos, shape, formedProp);
|
||||
|
||||
}
|
||||
|
||||
public static void unformForRemoval(Level level, BlockState state, BlockPos pos, ShapePart[] shape, @Nullable BooleanProperty formedProp) {
|
||||
if (level == null || level.isClientSide) return;
|
||||
|
||||
BlockEntity be = level.getBlockEntity(pos);
|
||||
if (!(be instanceof IMultiblockController controller)) return;
|
||||
|
||||
controller.setFormed(false);
|
||||
unlinkParts(level, state, pos, shape, formedProp);
|
||||
|
||||
}
|
||||
|
||||
private static void unlinkParts(Level level, BlockState state, BlockPos pos, ShapePart[] shape, @Nullable BooleanProperty formedProp) {
|
||||
if (level == null || level.isClientSide) return;
|
||||
|
||||
Direction facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
|
||||
for (ShapePart part : shape) {
|
||||
BlockPos partPos = pos.offset(rotateY(part.offset(), facing));
|
||||
BlockState st = level.getBlockState(partPos);
|
||||
|
||||
if (formedProp != null && st.hasProperty(formedProp) && st.getValue(formedProp)) {
|
||||
level.setBlock(partPos, st.setValue(formedProp, false), 3);
|
||||
}
|
||||
|
||||
BlockEntity be = level.getBlockEntity(partPos);
|
||||
if (be instanceof IMultiblockPart mbPart) {
|
||||
if (pos.equals(mbPart.getControllerPos())) {
|
||||
mbPart.setControllerPos(null);
|
||||
be.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void linkParts(Level level, BlockState state, BlockPos pos, ShapePart[] shape, @Nullable BooleanProperty formedProp) {
|
||||
if (level == null || level.isClientSide) return;
|
||||
|
||||
Direction facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
|
||||
for (ShapePart part : shape) {
|
||||
BlockPos partPos = pos.offset(rotateY(part.offset(), facing));
|
||||
BlockState st = level.getBlockState(partPos);
|
||||
|
||||
Aphelion.LOGGER.debug("[Multiblock] partPos={} block={} hasFormed={} formedVal={}",
|
||||
partPos,
|
||||
st.getBlock(),
|
||||
(formedProp != null && st.hasProperty(formedProp)),
|
||||
(formedProp != null && st.hasProperty(formedProp)) ? st.getValue(formedProp) : "n/a"
|
||||
);
|
||||
|
||||
if (formedProp != null && st.hasProperty(formedProp) && !st.getValue(formedProp)) {
|
||||
level.setBlock(partPos, st.setValue(formedProp, true), 3);
|
||||
st = level.getBlockState(partPos);
|
||||
}
|
||||
|
||||
BlockEntity be = level.getBlockEntity(partPos);
|
||||
if (be instanceof IMultiblockPart mbPart) {
|
||||
if (!pos.equals(mbPart.getControllerPos())) {
|
||||
mbPart.setControllerPos(pos);
|
||||
be.setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean structureMatchesDebug(
|
||||
Level level,
|
||||
BlockState controllerState,
|
||||
BlockPos controllerPos,
|
||||
ShapePart[] shape
|
||||
) {
|
||||
Direction facing = controllerState.getValue(BlockStateProperties.HORIZONTAL_FACING);
|
||||
|
||||
for (ShapePart part : shape) {
|
||||
BlockPos rotated = rotateY(part.offset(), facing);
|
||||
BlockPos worldPos = controllerPos.offset(rotated);
|
||||
|
||||
BlockState found = level.getBlockState(worldPos);
|
||||
|
||||
if (!part.rule().test(found)) {
|
||||
Aphelion.LOGGER.debug("[Multiblock] FAIL at offset=" + part.offset()
|
||||
+ " facing=" + facing
|
||||
+ " rotated=" + rotated
|
||||
+ " worldPos=" + worldPos
|
||||
+ " found=" + found.getBlock());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Aphelion.LOGGER.debug("[Multiblock] OK facing={} controllerPos={}", controllerState.getValue(BlockStateProperties.HORIZONTAL_FACING), controllerPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=east,formed=false,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,formed=false,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,formed=true,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,formed=true,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,formed=false,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace"
|
||||
},
|
||||
"facing=north,formed=false,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace"
|
||||
},
|
||||
"facing=north,formed=true,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed"
|
||||
},
|
||||
"facing=north,formed=true,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed"
|
||||
},
|
||||
"facing=south,formed=false,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,formed=false,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,formed=true,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,formed=true,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,formed=false,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,formed=false,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,formed=true,lit=false": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,formed=true,lit=true": {
|
||||
"model": "aphelion:block/electric_arc_furnace_formed",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=east,formed=false,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,formed=false,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,formed=true,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed",
|
||||
"y": 90
|
||||
},
|
||||
"facing=east,formed=true,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,formed=false,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller"
|
||||
},
|
||||
"facing=north,formed=false,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller"
|
||||
},
|
||||
"facing=north,formed=true,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed"
|
||||
},
|
||||
"facing=north,formed=true,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed"
|
||||
},
|
||||
"facing=south,formed=false,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,formed=false,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,formed=true,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed",
|
||||
"y": 180
|
||||
},
|
||||
"facing=south,formed=true,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed",
|
||||
"y": 180
|
||||
},
|
||||
"facing=west,formed=false,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,formed=false,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,formed=true,lit=false": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed",
|
||||
"y": 270
|
||||
},
|
||||
"facing=west,formed=true,lit=true": {
|
||||
"model": "aphelion:block/vacuum_arc_furnace_controller_formed",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"parent": "minecraft:block/orientable",
|
||||
"textures": {
|
||||
"front": "aphelion:block/electric_arc_furnace_front",
|
||||
"front": "aphelion:block/vacuum_arc_furnace_controller_front",
|
||||
"side": "minecraft:block/blast_furnace_side",
|
||||
"top": "minecraft:block/blast_furnace_top"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"parent": "minecraft:block/orientable",
|
||||
"textures": {
|
||||
"front": "aphelion:block/electric_arc_furnace_front_formed",
|
||||
"front": "aphelion:block/vacuum_arc_furnace_controller_front_formed",
|
||||
"side": "minecraft:block/blast_furnace_side",
|
||||
"top": "minecraft:block/blast_furnace_top"
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 247 B |
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 206 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Reference in New Issue
Block a user