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