diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java index 811b60a..43a78b8 100644 --- a/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java @@ -42,7 +42,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider, TickableBlockEntity { +public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider, TickableBlockEntity, IArcFurnaceLike { private final int SIZE = 4; private int ENERGY_CAPACITY = 64000; @@ -309,6 +309,11 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3); } + @Override + public IEnergyStorage getTrueEnergyStorage() { + return ENERGY_STORAGE; + } + 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); @@ -344,6 +349,11 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide return inventory; } + @Override + public ModEnergyStorage getEnergy() { + return ENERGY_STORAGE; + } + public void drops() { SimpleContainer inv = new SimpleContainer(inventory.getSlots()); for(int i = 0; i < inventory.getSlots(); i++) { diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/IArcFurnaceLike.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/IArcFurnaceLike.java new file mode 100644 index 0000000..d14ebb4 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/IArcFurnaceLike.java @@ -0,0 +1,20 @@ +package net.xevianlight.aphelion.block.entity.custom; + +import net.minecraft.core.Direction; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.energy.IEnergyStorage; +import net.neoforged.neoforge.items.ItemStackHandler; +import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage; + + +public interface IArcFurnaceLike { + ItemStackHandler getInventory(); + ModEnergyStorage getEnergy(); + + void sendUpdate(); + + BlockState getBlockState(); + + IEnergyStorage getTrueEnergyStorage(); +} diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/RocketAssemblerBlockEntity.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/RocketAssemblerBlockEntity.java index 500f611..cb90668 100644 --- a/src/main/java/net/xevianlight/aphelion/block/entity/custom/RocketAssemblerBlockEntity.java +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/RocketAssemblerBlockEntity.java @@ -16,6 +16,7 @@ import net.minecraft.world.level.block.Block; 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.AABB; import net.xevianlight.aphelion.Aphelion; import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity; import net.xevianlight.aphelion.core.init.ModBlockEntities; @@ -35,6 +36,7 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB Direction facing; BlockPos padScanStart = BlockPos.ZERO; private PadInfo padBounds; + RocketEntity lastRocket; public @Nullable PadInfo getPadBounds() { return padBounds; @@ -279,11 +281,14 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB if (level == null) return null; RocketStructure structure = scan(); RocketEntity rocket = null; + if (lastRocket != null) + lastRocket.disassemble(); if (structure != null && seatPos != null) { RocketStructure.clearCaptured(level, seatPos, structure); rocket = RocketEntity.spawnRocket(level, seatPos, structure); Aphelion.LOGGER.info("Spawn rocket result: {}", rocket); } + lastRocket = rocket; return rocket; } @@ -394,4 +399,6 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB this.loadAdditional(tag, registries); } } + + } diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/VacuumArcFurnaceControllerEntity.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/VacuumArcFurnaceControllerEntity.java index 01b0d2e..d4e3a18 100644 --- a/src/main/java/net/xevianlight/aphelion/block/entity/custom/VacuumArcFurnaceControllerEntity.java +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/VacuumArcFurnaceControllerEntity.java @@ -47,7 +47,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Optional; -public class VacuumArcFurnaceControllerEntity extends BlockEntity implements MenuProvider, IMultiblockController, TickableBlockEntity { +public class VacuumArcFurnaceControllerEntity extends BlockEntity implements MenuProvider, IMultiblockController, TickableBlockEntity, IArcFurnaceLike { private final int SIZE = 4; private final int ENERGY_CAPACITY = 64000; @@ -357,7 +357,8 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men return isFormed() ? ENERGY_STORAGE : null; } - public IEnergyStorage getTrueEnergyStorage(@Nullable Direction direction) { + @Override + public IEnergyStorage getTrueEnergyStorage() { return this.ENERGY_STORAGE; } diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/renderer/RocketAssemblerBlockEntityRenderer.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/renderer/RocketAssemblerBlockEntityRenderer.java index 8c5f065..3d93480 100644 --- a/src/main/java/net/xevianlight/aphelion/block/entity/custom/renderer/RocketAssemblerBlockEntityRenderer.java +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/renderer/RocketAssemblerBlockEntityRenderer.java @@ -19,6 +19,24 @@ public class RocketAssemblerBlockEntityRenderer implements BlockEntityRenderer { + Entity entity = EntityArgument.getEntity(context, "entity"); + + if (entity instanceof RocketEntity rocket) { + if (rocket.disassemble()) { + context.getSource().sendSuccess(() -> Component.translatable("command.aphelion.rocket.disassemble.success"), true); + } else { + context.getSource().sendFailure(Component.translatable("command.aphelion.rocket.disassemble.failure")); + } + } else { + context.getSource().sendFailure(Component.translatable("command.aphelion.rocket.entity_invalid")); + } + return 1; + }) + ) ) ) diff --git a/src/main/java/net/xevianlight/aphelion/entites/vehicles/RocketEntity.java b/src/main/java/net/xevianlight/aphelion/entites/vehicles/RocketEntity.java index 8c21eed..eebe4e2 100644 --- a/src/main/java/net/xevianlight/aphelion/entites/vehicles/RocketEntity.java +++ b/src/main/java/net/xevianlight/aphelion/entites/vehicles/RocketEntity.java @@ -506,4 +506,54 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa return InteractionResult.sidedSuccess(level().isClientSide); } + public boolean disassemble() { + if (level().isClientSide) return false; + if (!(level() instanceof ServerLevel server)) return false; + + // Optional: only allow when not in flight + if (getPhase() == FlightPhase.ASCEND || getPhase() == FlightPhase.TRANSIT || getPhase() == FlightPhase.DESCEND) { + return false; + } + + // Kick riders off first (so we don't place blocks inside them) + ejectPassengers(); + + // Anchor: blocks were captured relative to the scan origin. + // Your rocket is spawned at seatPos + (0.5, 0, 0.5), so we convert back to the block origin. + BlockPos origin = BlockPos.containing(getX(), getY(), getZ()); + + // Place blocks + for (int i = 0; i < structure.size(); i++) { + int packed = structure.packedPosAt(i); + + int dx = RocketStructure.unpackX(packed); + int dy = RocketStructure.unpackY(packed); + int dz = RocketStructure.unpackZ(packed); + + BlockPos wp = origin.offset(dx, dy, dz); + var stateToPlace = structure.stateAt(i); + + // Don't place air (shouldn't exist in structure anyway, but safe) + if (stateToPlace.isAir()) continue; + + // Safety: don't overwrite existing blocks + if (!server.getBlockState(wp).isAir()) { + // If you want strict behavior, abort entirely: + // return false; + + // Otherwise just skip conflicts: + continue; + } + + // Extra safety: avoid accidentally placing into portal/void/etc if desired + // if (!server.isInWorldBounds(wp)) continue; + + server.setBlock(wp, stateToPlace, 3); + } + + // Remove the rocket entity + discard(); // preferred over kill() for "just remove this entity" + return true; + } + } \ No newline at end of file diff --git a/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java index 7afa990..8b8901a 100644 --- a/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java +++ b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java @@ -12,13 +12,14 @@ 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.entity.custom.ElectricArcFurnaceEntity; +import net.xevianlight.aphelion.block.entity.custom.IArcFurnaceLike; import net.xevianlight.aphelion.util.EnergyItemSlot; import net.xevianlight.aphelion.util.ExtractOnlySlot; import org.jetbrains.annotations.NotNull; public class ElectricArcFurnaceMenu extends AbstractContainerMenu { - public final ElectricArcFurnaceEntity blockEntity; + public final IArcFurnaceLike blockEntity; private final Level level; private final ContainerData data; @@ -28,17 +29,17 @@ public class ElectricArcFurnaceMenu extends AbstractContainerMenu { public ElectricArcFurnaceMenu(int i, Inventory inventory, BlockEntity blockEntity, ContainerData data) { super(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), i); - this.blockEntity = ((ElectricArcFurnaceEntity) blockEntity); + this.blockEntity = ((IArcFurnaceLike) blockEntity); this.level = inventory.player.level(); this.data = data; addPlayerInventory(inventory); addPlayerHotbar(inventory); - this.addSlot(new EnergyItemSlot(this.blockEntity.inventory, ElectricArcFurnaceEntity.ENERGY_SLOT, 8, 54)); - this.addSlot(new SlotItemHandler(this.blockEntity.inventory, ElectricArcFurnaceEntity.INPUT_SLOT, 63, 35)); - this.addSlot(new SlotItemHandler(this.blockEntity.inventory, ElectricArcFurnaceEntity.SECONDARY_INPUT_SLOT, 40, 35)); - this.addSlot(new ExtractOnlySlot(this.blockEntity.inventory, ElectricArcFurnaceEntity.OUTPUT_SLOT, 125, 35)); + this.addSlot(new EnergyItemSlot(this.blockEntity.getInventory(), ElectricArcFurnaceEntity.ENERGY_SLOT, 8, 54)); + this.addSlot(new SlotItemHandler(this.blockEntity.getInventory(), ElectricArcFurnaceEntity.INPUT_SLOT, 63, 35)); + this.addSlot(new SlotItemHandler(this.blockEntity.getInventory(), ElectricArcFurnaceEntity.SECONDARY_INPUT_SLOT, 40, 35)); + this.addSlot(new ExtractOnlySlot(this.blockEntity.getInventory(), ElectricArcFurnaceEntity.OUTPUT_SLOT, 125, 35)); addDataSlots(data); } diff --git a/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java index 3e58ab9..944b708 100644 --- a/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java +++ b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java @@ -62,8 +62,8 @@ public class ElectricArcFurnaceScreen extends AbstractContainerScreen