diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/BasicRocketFuelTank.java b/src/main/java/net/xevianlight/aphelion/block/custom/BasicRocketFuelTank.java
new file mode 100644
index 0000000..d0c8231
--- /dev/null
+++ b/src/main/java/net/xevianlight/aphelion/block/custom/BasicRocketFuelTank.java
@@ -0,0 +1,14 @@
+package net.xevianlight.aphelion.block.custom;
+
+import net.xevianlight.aphelion.block.custom.base.BaseRocketFuelTank;
+
+public class BasicRocketFuelTank extends BaseRocketFuelTank {
+ public BasicRocketFuelTank(Properties properties) {
+ super(properties);
+ }
+
+ @Override
+ public int getFuelCapacity() {
+ return 1000;
+ }
+}
diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/base/BaseRocketFuelTank.java b/src/main/java/net/xevianlight/aphelion/block/custom/base/BaseRocketFuelTank.java
new file mode 100644
index 0000000..e5c7d0c
--- /dev/null
+++ b/src/main/java/net/xevianlight/aphelion/block/custom/base/BaseRocketFuelTank.java
@@ -0,0 +1,29 @@
+package net.xevianlight.aphelion.block.custom.base;
+
+import net.minecraft.world.item.Item;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.SoundType;
+
+public class BaseRocketFuelTank extends Block implements IRocketFuelUpgrade {
+ public BaseRocketFuelTank(Properties properties) {
+ super(properties);
+ }
+
+ 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 int getFuelCapacity() {
+ return 0;
+ }
+}
diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketEnergyUpgrade.java b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketEnergyUpgrade.java
new file mode 100644
index 0000000..0df6990
--- /dev/null
+++ b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketEnergyUpgrade.java
@@ -0,0 +1,21 @@
+package net.xevianlight.aphelion.block.custom.base;
+
+/**
+ * Used for blocks which should provide energy storage capacity to a rocket.
+ *
Note that blocks implementing this interface should not store energy themselves.
+ * Rockets determine their energy capacity from the sum of these blocks installed on them.
+ * Keep in mind that {@code TileEntity} blocks cannot be included in a {@code RocketStructure}.
+ */
+public interface IRocketEnergyUpgrade {
+ /**
+ * Used to determine how much FE of energy storage a rocket receives from having this block is installed.
+ */
+ int getEnergyCapacity();
+
+ /**
+ * Used to determine how much FE transfer rate bonus a rocket receives from having this block is installed. This is added onto the base rockets energy transfer limit.
+ */
+ default int getMaxTransferBonus() {
+ return 0;
+ };
+}
diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketFluidUpgrade.java b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketFluidUpgrade.java
new file mode 100644
index 0000000..31544ae
--- /dev/null
+++ b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketFluidUpgrade.java
@@ -0,0 +1,14 @@
+package net.xevianlight.aphelion.block.custom.base;
+
+/**
+ * Used for blocks which should provide fluid storage capacity to a rocket.
+ * Note that blocks implementing this interface should not store fluids themselves.
+ * Rockets determine their fluid container capacity from the sum of these blocks installed on them.
+ * Keep in mind that {@code TileEntity} blocks cannot be included in a {@code RocketStructure}.
+ */
+public interface IRocketFluidUpgrade {
+ /**
+ * Used to determine how many millibuckets of fluid storage a rocket receives from having this block is installed.
+ */
+ int getFluidCapacity();
+}
diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketFuelUpgrade.java b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketFuelUpgrade.java
new file mode 100644
index 0000000..114bb65
--- /dev/null
+++ b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketFuelUpgrade.java
@@ -0,0 +1,16 @@
+package net.xevianlight.aphelion.block.custom.base;
+
+import net.neoforged.neoforge.fluids.capability.templates.FluidTank;
+
+/**
+ * Used for blocks which should provide fuel storage capacity to a rocket.
+ * Note that blocks implementing this interface should not store fuel themselves.
+ * Rockets determine their fuel container capacity from the sum of these blocks installed on them.
+ * Keep in mind that {@code TileEntity} blocks cannot be included in a {@code RocketStructure}.
+ */
+public interface IRocketFuelUpgrade {
+ /**
+ * Used to determine how many millibuckets of fuel storage a rocket receives from having this block is installed.
+ */
+ int getFuelCapacity();
+}
diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketInventoryUpgrade.java b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketInventoryUpgrade.java
new file mode 100644
index 0000000..f8dfba9
--- /dev/null
+++ b/src/main/java/net/xevianlight/aphelion/block/custom/base/IRocketInventoryUpgrade.java
@@ -0,0 +1,15 @@
+package net.xevianlight.aphelion.block.custom.base;
+
+/**
+ * Used for blocks which should provide item slots to a rockets inventory.
+ * Note that blocks implementing this interface should not store items themselves.
+ * Rockets determine their inventory slot count from the sum of these blocks installed on them.
+ * Keep in mind that {@code TileEntity} blocks cannot be included in a {@code RocketStructure}.
+ */
+public interface IRocketInventoryUpgrade {
+ /**
+ * Used to determine how many inventory slots a rocket receives from having this block installed.
+ */
+
+ int getSlotCapacity();
+}
diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java b/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java
index 3ba83df..b22d7ce 100644
--- a/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java
+++ b/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java
@@ -33,5 +33,9 @@
}
public abstract void onEnergyChanged();
+
+ public void setCapacity(int capacity) {
+ this.capacity = capacity;
+ }
}
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 eebe4e2..8034db2 100644
--- a/src/main/java/net/xevianlight/aphelion/entites/vehicles/RocketEntity.java
+++ b/src/main/java/net/xevianlight/aphelion/entites/vehicles/RocketEntity.java
@@ -2,6 +2,7 @@ package net.xevianlight.aphelion.entites.vehicles;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
+import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
@@ -13,13 +14,16 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.tags.FluidTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.*;
+import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.VehicleEntity;
import net.minecraft.world.item.Item;
+import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
@@ -27,9 +31,14 @@ import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.entity.IEntityWithComplexSpawn;
+import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidType;
+import net.neoforged.neoforge.fluids.capability.templates.FluidTank;
+import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.Aphelion;
+import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
import net.xevianlight.aphelion.core.init.ModEntities;
+import net.xevianlight.aphelion.fluid.ModFluids;
import net.xevianlight.aphelion.util.RocketStructure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -63,6 +72,43 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
private static final EntityDataAccessor STRUCTURE_TAG =
SynchedEntityData.defineId(RocketEntity.class, EntityDataSerializers.COMPOUND_TAG);
+ private final FluidTank FUEL_TANK = newFuelTank(0);
+ private final FluidTank FLUID_STORAGE = newFluidTank(0);
+ private final ModEnergyStorage ENERGY_STORAGE = newEnergyStorage(0, 0);
+ private final ItemStackHandler INVENTORY = new ItemStackHandler(0);
+
+ public ItemStackHandler getInventory() {
+ return INVENTORY;
+ }
+
+ private static @NotNull FluidTank newFluidTank(int capacity) {
+ return new FluidTank(capacity) {
+ @Override
+ public boolean isFluidValid(@NotNull FluidStack stack) {
+ return true;
+ }
+ };
+ }
+
+ private static @NotNull FluidTank newFuelTank(int capacity) {
+ return new FluidTank(capacity) {
+ @Override
+ public boolean isFluidValid(@NotNull FluidStack stack) {
+ return stack.is(FluidTags.WATER);
+ }
+ };
+ }
+
+ private static @NotNull ModEnergyStorage newEnergyStorage(int capacity, int transfer) {
+ return new ModEnergyStorage(capacity, transfer) {
+ @Override
+ public void onEnergyChanged() {
+
+ }
+ };
+ }
+
+
public static RocketEntity spawnRocket(Level level, BlockPos pos, RocketStructure structure) {
if (level.isClientSide) return null;
@@ -79,9 +125,25 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
rocket.setStructure(structure);
level.addFreshEntity(rocket);
+ rocket.FUEL_TANK.setFluid(new FluidStack(ModFluids.OIL.get(), 1000));
+ rocket.INVENTORY.setSize(rocket.INVENTORY.getSlots() + 1);
+ rocket.INVENTORY.insertItem(0, new ItemStack(Items.DIAMOND, 1), false);
+
return rocket;
}
+ private void recalculateCapacitiesFromStructure() {
+ int inv = RocketStructure.calculateInventoryCapacity(structure);
+ int fuelCap = RocketStructure.calculateFuelCapacity(structure);
+ int fluidCap = RocketStructure.calculateFluidCapacity(structure);
+ int energyCap = RocketStructure.calculateEnergyCapacity(structure);
+
+ INVENTORY.setSize(inv);
+ FUEL_TANK.setCapacity(fuelCap);
+ FLUID_STORAGE.setCapacity(fluidCap);
+ ENERGY_STORAGE.setCapacity(energyCap);
+ }
+
public void launchTo(ResourceKey dim, @Nullable BlockPos pos) {
if (level().isClientSide) return;
@@ -119,7 +181,6 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
}
case DESCEND -> tickDescend();
}
- // Simple upward movement
}
@@ -280,12 +341,13 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
this.refreshDimensions();
this.setBoundingBox(this.makeBoundingBox());
- // prevent any internal “snap” from sticking
this.moveTo(x, y, z, yRot, xRot);
if (!level().isClientSide) {
this.entityData.set(STRUCTURE_TAG, this.structure.save());
}
+
+ recalculateCapacitiesFromStructure();
}
@Override
@@ -326,9 +388,12 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
@Override
protected void readAdditionalSaveData(CompoundTag tag) {
+ HolderLookup.Provider registries = level().registryAccess();
+
if (tag.contains("RocketStructure")) {
CompoundTag rocketTag = tag.getCompound("RocketStructure");
structure.load(rocketTag);
+ recalculateCapacitiesFromStructure();
// Immediately apply correct bbox on load (server + client)
double x = getX(), y = getY(), z = getZ();
@@ -362,10 +427,22 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
if (tag.contains("FlightPhase", Tag.TAG_BYTE)) {
setPhase(FlightPhase.values()[tag.getByte("FlightPhase")]);
}
+
+ if (tag.contains("Inventory", CompoundTag.TAG_COMPOUND)){
+ INVENTORY.deserializeNBT(registries, tag.getCompound("Inventory"));
+ }
+
+ FUEL_TANK.readFromNBT(registries, tag);
+ FLUID_STORAGE.readFromNBT(registries, tag);
+
+ if (tag.contains("Energy", CompoundTag.TAG_COMPOUND)) {
+ ENERGY_STORAGE.deserializeNBT(registries, tag.getCompound("Energy"));
+ }
}
@Override
protected void addAdditionalSaveData(CompoundTag tag) {
+ HolderLookup.Provider registries = level().registryAccess();
tag.put("RocketStructure", structure.save());
if (targetDim != null)
tag.putString("TargetDim", targetDim.location().toString());
@@ -376,6 +453,10 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
tag.putDouble("LandingX", landingPosX);
tag.putDouble("LandingZ", landingPosZ);
tag.putDouble("yVelocity", yVel);
+ tag.put("Inventory", INVENTORY.serializeNBT(registries));
+ tag = FUEL_TANK.writeToNBT(registries, tag);
+ tag = FLUID_STORAGE.writeToNBT(registries, tag);
+ tag.put("Energy", ENERGY_STORAGE.serializeNBT(registries));
}
public @Nullable BlockPos getTargetPos() {
@@ -438,7 +519,7 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
}
- public Vec3 getSeatWorldPos(int seatIndex, float partialTicks) {
+ public Vec3 getSeatWorldPos(int seatIndex) {
int packed = structure.packedSeatAt(seatIndex);
int dx = RocketStructure.unpackX(packed);
@@ -449,10 +530,10 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
}
@Override
- public void positionRider(Entity passenger, MoveFunction move) {
+ public void positionRider(@NotNull Entity passenger, @NotNull MoveFunction move) {
if (!this.hasPassenger(passenger)) return;
- Vec3 seat = getSeatWorldPos(0, 0); // primary seat
+ Vec3 seat = getSeatWorldPos(0); // primary seat
move.accept(passenger, seat.x, seat.y, seat.z);
}
@@ -473,7 +554,7 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
public void applyStructureTag(CompoundTag structureTag) {
this.structure.load(structureTag);
- this.refreshDimensions(); // if your hitbox/eye depends on structure
+ this.refreshDimensions();
}
private AABB computeWorldAABBFromStructure() {
@@ -510,16 +591,14 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
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;
- }
+ // In rare instances we can disassemble a rocket AFTER it has been killed.
+ // This usually only happens if another class instance still has a reference to this object stored and calls rocketEntity.disassemble().
+ // This SHOULD fix that
+ if (!this.isAlive()) return false; // dead
+ if (this.isRemoved()) return false; // discarded / removed
- // 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
@@ -538,16 +617,9 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
// 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);
}
@@ -556,4 +628,30 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
return true;
}
+ public static void dropItemStackHandler(ServerLevel level, Vec3 pos, ItemStackHandler handler) {
+ for (int i = 0; i < handler.getSlots(); i++) {
+ ItemStack stack = handler.getStackInSlot(i);
+ if (!stack.isEmpty()) {
+ ItemStack toDrop = stack.copy();
+ handler.setStackInSlot(i, ItemStack.EMPTY);
+
+ ItemEntity ent = new ItemEntity(level, pos.x, pos.y, pos.z, toDrop);
+ level.addFreshEntity(ent);
+ }
+ }
+ }
+
+ @Override
+ public void kill() {
+ if (!level().isClientSide())
+ dropItemStackHandler((ServerLevel) level(), position(), INVENTORY);
+ super.kill();
+ }
+
+ @Override
+ public void onRemovedFromLevel() {
+ if (!level().isClientSide())
+ dropItemStackHandler((ServerLevel) level(), position(), INVENTORY);
+ super.onRemovedFromLevel();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java b/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java
index e0d3e92..4767b1f 100644
--- a/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java
+++ b/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java
@@ -13,6 +13,8 @@ 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.core.init.ModEntities;
+import net.xevianlight.aphelion.entites.vehicles.RocketEntity;
import net.xevianlight.aphelion.network.RocketPayloadHandlers;
import net.xevianlight.aphelion.network.PartitionPayloadHandler;
import net.xevianlight.aphelion.network.packet.PartitionPayload;
@@ -30,6 +32,8 @@ public class ModBusEvents {
// event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.VAF_MULTIBLOCK_DUMMY_ENTITY.get(), VAFMultiblockDummyBlockEntity::getItemHandler);
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.VAF_MULTIBLOCK_DUMMY_ENTITY.get(), BaseMultiblockDummyBlockEntity::getItemHandler);
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.VAF_MULTIBLOCK_DUMMY_ENTITY.get(), BaseMultiblockDummyBlockEntity::getEnergyStorage);
+
+ event.registerEntity(Capabilities.ItemHandler.ENTITY, ModEntities.ROCKET.get(), (rocket, ctx) -> rocket.getInventory());
}
@SubscribeEvent
diff --git a/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java b/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java
index 9580e5a..749ddd7 100644
--- a/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java
+++ b/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java
@@ -24,19 +24,19 @@ public class ModFluids {
public static final DeferredRegister FLUIDS =
DeferredRegister.create(BuiltInRegistries.FLUID, Aphelion.MOD_ID);
- public static final Supplier SOURCE_OIL_FLUID = FLUIDS.register("oil",
+ public static final Supplier OIL = FLUIDS.register("oil",
() -> new BaseFlowingFluid.Source(ModFluids.OIL_PROPERTIES));
- public static final Supplier FLOWING_OIL_FLUID = FLUIDS.register("flowing_oil",
+ public static final Supplier FLOWING_OIL = FLUIDS.register("flowing_oil",
() -> new BaseFlowingFluid.Flowing(ModFluids.OIL_PROPERTIES));
public static final DeferredBlock OIL_BLOCK = ModBlocks.BLOCKS.register("oil",
- () -> new LiquidBlock(ModFluids.SOURCE_OIL_FLUID.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable()));
+ () -> new LiquidBlock(ModFluids.OIL.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable()));
public static final DeferredItem- OIL_BUCKET = ModItems.ITEMS.registerItem("oil_bucket",
- properties -> new BucketItem(ModFluids.SOURCE_OIL_FLUID.get(), properties.stacksTo(1).craftRemainder(Items.BUCKET)));
+ properties -> new BucketItem(ModFluids.OIL.get(), properties.stacksTo(1).craftRemainder(Items.BUCKET)));
public static final BaseFlowingFluid.Properties OIL_PROPERTIES = new BaseFlowingFluid.Properties(
- ModFluidTypes.OIL_FLUID_TYPE, SOURCE_OIL_FLUID, FLOWING_OIL_FLUID)
+ ModFluidTypes.OIL_FLUID_TYPE, OIL, FLOWING_OIL)
.slopeFindDistance(2).levelDecreasePerBlock(2).tickRate(10)
.block(ModFluids.OIL_BLOCK).bucket(ModFluids.OIL_BUCKET);
diff --git a/src/main/java/net/xevianlight/aphelion/util/RocketStructure.java b/src/main/java/net/xevianlight/aphelion/util/RocketStructure.java
index 13ae8ef..054fe68 100644
--- a/src/main/java/net/xevianlight/aphelion/util/RocketStructure.java
+++ b/src/main/java/net/xevianlight/aphelion/util/RocketStructure.java
@@ -11,6 +11,11 @@ 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.DoubleBlockHalf;
import net.minecraft.world.phys.AABB;
+import net.xevianlight.aphelion.block.custom.base.IRocketEnergyUpgrade;
+import net.xevianlight.aphelion.block.custom.base.IRocketFluidUpgrade;
+import net.xevianlight.aphelion.block.custom.base.IRocketFuelUpgrade;
+import net.xevianlight.aphelion.block.custom.base.IRocketInventoryUpgrade;
+import org.apache.commons.lang3.NotImplementedException;
import java.util.ArrayList;
import java.util.List;
@@ -151,27 +156,6 @@ public final class RocketStructure {
return new Extents(minX, minY, minZ, maxX, maxY, maxZ);
}
- public static RocketStructure capture(Level level, BlockPos origin, int rx, int ry, int rz) {
- return new RocketStructure(s -> {
- for (int dy = -ry; dy <= ry; dy++) {
- for (int dx = -rx; dx <= rx; dx++) {
- for (int dz = -rz; dz <= rz; dz++) {
- BlockPos p = origin.offset(dx, dy, dz);
- BlockState st = level.getBlockState(p);
-
- // Skip air and unbreakables/forbidden blocks as you like
- if (st.isAir()) continue;
-
- // Optional: ignore the assembler block itself
- // if (p.equals(origin)) continue;
-
- s.add(dx, dy, dz, st);
- }
- }
- }
- });
- }
-
public static void clearCaptured(Level level, BlockPos origin, RocketStructure struct) {
final int flags = Block.UPDATE_CLIENTS;
@@ -230,4 +214,60 @@ public final class RocketStructure {
public void addSeatOffset(int dx, int dy, int dz) {
seatOffsets.add(packPos(dx, dy, dz));
}
+
+ public static int calculateInventoryCapacity(RocketStructure structure) {
+ int totalSlots = 0;
+ for (int i = 0; i < structure.size(); i++) {
+ BlockState st = structure.stateAt(i);
+ Block block = st.getBlock();
+
+ if (block instanceof IRocketInventoryUpgrade upgrade) {
+ int slots = upgrade.getSlotCapacity();
+ if (slots > 0) totalSlots += slots;
+ }
+ }
+ return totalSlots;
+ }
+
+ public static int calculateFuelCapacity(RocketStructure structure) {
+ int totalMB = 0;
+ for (int i = 0; i < structure.size(); i++) {
+ BlockState st = structure.stateAt(i);
+ Block block = st.getBlock();
+
+ if (block instanceof IRocketFuelUpgrade upgrade) {
+ int mb = upgrade.getFuelCapacity();
+ if (mb > 0) totalMB += mb;
+ }
+ }
+ return totalMB;
+ }
+
+ public static int calculateFluidCapacity(RocketStructure structure) {
+ int totalMB = 0;
+ for (int i = 0; i < structure.size(); i++) {
+ BlockState st = structure.stateAt(i);
+ Block block = st.getBlock();
+
+ if (block instanceof IRocketFluidUpgrade upgrade) {
+ int mb = upgrade.getFluidCapacity();
+ if (mb > 0) totalMB += mb;
+ }
+ }
+ return totalMB;
+ }
+
+ public static int calculateEnergyCapacity(RocketStructure structure) {
+ int totalFE = 0;
+ for (int i = 0; i < structure.size(); i++) {
+ BlockState st = structure.stateAt(i);
+ Block block = st.getBlock();
+
+ if (block instanceof IRocketEnergyUpgrade upgrade) {
+ int fe = upgrade.getEnergyCapacity();
+ if (fe > 0) totalFE += fe;
+ }
+ }
+ return totalFE;
+ }
}
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/0010.json b/src/main/resources/assets/aphelion/models/block/launch_pad/0010.json
index abe8a7d..f475b54 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/0010.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/0010.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/0010",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/0010"
+ "bottom": "aphelion:block/launch_pad/1000"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/0011.json b/src/main/resources/assets/aphelion/models/block/launch_pad/0011.json
index 1f56f7a..62e1e29 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/0011.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/0011.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/0011",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/0011"
+ "bottom": "aphelion:block/launch_pad/1001"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/0110.json b/src/main/resources/assets/aphelion/models/block/launch_pad/0110.json
index 66b9dd2..f667f7b 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/0110.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/0110.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/0110",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/0110"
+ "bottom": "aphelion:block/launch_pad/1100"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/0111.json b/src/main/resources/assets/aphelion/models/block/launch_pad/0111.json
index 7e21cf9..60a2ec7 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/0111.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/0111.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/0111",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/0111"
+ "bottom": "aphelion:block/launch_pad/1101"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/1000.json b/src/main/resources/assets/aphelion/models/block/launch_pad/1000.json
index 13a527f..90afa99 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/1000.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/1000.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/1000",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/1000"
+ "bottom": "aphelion:block/launch_pad/0010"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/1001.json b/src/main/resources/assets/aphelion/models/block/launch_pad/1001.json
index b7e6827..cca9518 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/1001.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/1001.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/1001",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/1001"
+ "bottom": "aphelion:block/launch_pad/0011"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/1100.json b/src/main/resources/assets/aphelion/models/block/launch_pad/1100.json
index a7dcf91..292d695 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/1100.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/1100.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/1100",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/1100"
+ "bottom": "aphelion:block/launch_pad/0110"
}
}
\ No newline at end of file
diff --git a/src/main/resources/assets/aphelion/models/block/launch_pad/1101.json b/src/main/resources/assets/aphelion/models/block/launch_pad/1101.json
index 74a0be8..39302cc 100644
--- a/src/main/resources/assets/aphelion/models/block/launch_pad/1101.json
+++ b/src/main/resources/assets/aphelion/models/block/launch_pad/1101.json
@@ -3,6 +3,6 @@
"textures": {
"top": "aphelion:block/launch_pad/1101",
"side": "aphelion:block/launch_pad/topbottom",
- "bottom": "aphelion:block/launch_pad/1101"
+ "bottom": "aphelion:block/launch_pad/0111"
}
}
\ No newline at end of file