Basic StationRocketEngineBlock functionality. StationFlightComputerBlock simply sets traveling to true. Rocket crash fixes. TEST

This commit is contained in:
XevianLight
2026-03-28 19:56:15 -06:00
parent 0f4b98a912
commit 341ed8a17d
38 changed files with 705 additions and 103 deletions

View File

@@ -1,6 +1,8 @@
package net.xevianlight.aphelion;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.api.distmarker.Dist;
@@ -127,14 +129,15 @@ public class Aphelion {
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) {
event.enqueueWork(() -> {
// ItemBlockRenderTypes.setRenderLayer(ModFluids.SOURCE_OIL_FLUID.get(), RenderType.translucent());
// ItemBlockRenderTypes.setRenderLayer(ModFluids.FLOWING_OIL_FLUID.get(), RenderType.translucent());
ItemBlockRenderTypes.setRenderLayer(ModFluids.ROCKET_FUEL.get(), RenderType.translucent());
ItemBlockRenderTypes.setRenderLayer(ModFluids.FLOWING_ROCKET_FUEL.get(), RenderType.translucent());
});
}
@SubscribeEvent
public static void onClientExtensions(RegisterClientExtensionsEvent event) {
event.registerFluidType(((BaseFluidType) ModFluidTypes.OIL_FLUID_TYPE.get()).getClientFluidTypeExtensions(), ModFluidTypes.OIL_FLUID_TYPE.get());
event.registerFluidType(((BaseFluidType) ModFluidTypes.ROCKET_FUEL_FLUID_TYPE.get()).getClientFluidTypeExtensions(), ModFluidTypes.ROCKET_FUEL_FLUID_TYPE.get());
}
@SubscribeEvent

View File

@@ -0,0 +1,15 @@
package net.xevianlight.aphelion.block.custom;
import net.xevianlight.aphelion.block.custom.base.BaseRocketContainer;
import net.xevianlight.aphelion.block.custom.base.BaseRocketFuelTank;
public class BasicRocketContainer extends BaseRocketContainer {
public BasicRocketContainer(Properties properties) {
super(properties);
}
@Override
public int getSlotCapacity() {
return 9;
}
}

View File

@@ -0,0 +1,42 @@
package net.xevianlight.aphelion.block.custom;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.xevianlight.aphelion.block.custom.base.BasicHorizontalEntityBlock;
import net.xevianlight.aphelion.block.entity.custom.StationFlightComputerBlockEntity;
import net.xevianlight.aphelion.core.saveddata.types.PartitionData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class StationFlightComputerBlock extends BasicHorizontalEntityBlock {
public static final MapCodec<StationFlightComputerBlock> CODEC = simpleCodec(StationFlightComputerBlock::new);
public StationFlightComputerBlock(Properties properties) {
super(properties, true);
}
@Override
protected @NotNull MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}
@Override
public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
return new StationFlightComputerBlockEntity(blockPos, blockState);
}
@Override
protected void onRemove(BlockState state, @NotNull Level level, @NotNull BlockPos pos, BlockState newState, boolean movedByPiston) {
if (level.getBlockEntity(pos) instanceof StationFlightComputerBlockEntity computerBE) {
PartitionData data = computerBE.getData();
if (data != null) {
data.setTraveling(false);
}
}
}
}

View File

@@ -0,0 +1,99 @@
package net.xevianlight.aphelion.block.custom;
import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
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.phys.BlockHitResult;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.common.SoundActions;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.FluidType;
import net.neoforged.neoforge.fluids.FluidUtil;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.custom.base.StationEngineBlock;
import net.xevianlight.aphelion.block.entity.custom.StationRocketEngineBlockEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class StationRocketEngineBlock extends StationEngineBlock {
public StationRocketEngineBlock(Properties properties) {
super(properties);
}
@Override
public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
return new StationRocketEngineBlockEntity(blockPos, blockState);
}
@Override
public @NotNull ItemInteractionResult useItemOn(
ItemStack stack,
BlockState state,
Level level,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hit) {
// Only intercept on client if holding a fluid container, otherwise let block placement through
if (level.isClientSide) {
return FluidUtil.getFluidHandler(stack).isPresent()
? ItemInteractionResult.SUCCESS
: ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}
BlockEntity be = level.getBlockEntity(pos);
if (!(be instanceof StationRocketEngineBlockEntity engineBE)) {
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}
IFluidHandler tankHandler = level.getCapability(
Capabilities.FluidHandler.BLOCK, pos, state, be, null
);
if (tankHandler == null) {
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}
FluidStack fluidBeforeInteraction = FluidUtil.getFluidContained(player.getItemInHand(hand))
.orElse(FluidStack.EMPTY);
boolean success = FluidUtil.interactWithFluidHandler(player, hand, tankHandler);
if (success) {
FluidStack tankFluid = tankHandler.getFluidInTank(0);
FluidStack relevantFluid = fluidBeforeInteraction.isEmpty() ? tankFluid : fluidBeforeInteraction;
Aphelion.LOGGER.info("fluidBeforeInteraction: {}", fluidBeforeInteraction);
Aphelion.LOGGER.info("tankFluid: {}", tankFluid);
Aphelion.LOGGER.info("relevantFluid: {}", relevantFluid);
if (!relevantFluid.isEmpty()) {
FluidType fluidType = relevantFluid.getFluid().getFluidType();
SoundEvent sound = fluidBeforeInteraction.isEmpty()
? fluidType.getSound(SoundActions.BUCKET_FILL)
: fluidType.getSound(SoundActions.BUCKET_EMPTY);
Aphelion.LOGGER.info("fluidType: {}", fluidType);
Aphelion.LOGGER.info("sound: {}", sound);
if (sound != null) {
Aphelion.LOGGER.info("Playing sound!");
level.playSound(null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F);
}
}
return ItemInteractionResult.CONSUME;
}
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
}
}

View File

@@ -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 BaseRocketContainer extends Block implements IRocketInventoryUpgrade {
public BaseRocketContainer(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 getSlotCapacity() {
return 0;
}
}

View File

@@ -29,6 +29,10 @@ public abstract class BasicEntityBlock extends BaseEntityBlock {
return RenderShape.MODEL;
}
public static Properties getProperties() {
return Properties.of();
}
public static Item.Properties getItemProperties() {
return new Item.Properties();
}

View File

@@ -0,0 +1,27 @@
package net.xevianlight.aphelion.block.custom.base;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public class StationEngineBlock extends BasicEntityBlock {
public static final MapCodec<StationEngineBlock> CODEC = simpleCodec(StationEngineBlock::new);
protected StationEngineBlock(Properties properties) {
super(properties, true);
}
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}
@Override
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return null;
}
}

View File

@@ -1,32 +0,0 @@
package net.xevianlight.aphelion.block.custom.base;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.xevianlight.aphelion.core.saveddata.types.PartitionData;
import net.xevianlight.aphelion.util.Constants;
public class StationRocketEngineBlockEntity extends StationEngineBlockEntity {
/// Seconds to travel 1 AU
private final double SECONDS_PER_AU = 60;
/// AU per tick
private final double SPEED = 1/(SECONDS_PER_AU*20);
@Override
public double getTravelSpeed() {
return SPEED;
}
protected StationRocketEngineBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState blockState) {
// TODO change type to ModBlockEntities.STATION_ROCKET_ENGINE_BLOCK_ENTITY.get()
super(type, pos, blockState);
}
@Override
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
super.serverTick(level, time, state, pos); // IMPORTANT!!!
}
}

View File

@@ -58,6 +58,8 @@ public interface TickableBlockEntity {
* <p>Implementations should return {@code true} once initialization has finished
* to prevent {@code firstTick} from running again.</p>
*
* <p>Returns {@code true} if not implemented.</p>
*
* @return {@code true} if initialization has completed, {@code false} otherwise
*/
default boolean isInitialized() {
@@ -74,6 +76,8 @@ public interface TickableBlockEntity {
* <p>Implementations should perform any required setup and ensure that
* {@code isInitialized()} returns {@code true} afterward.</p>
*
* <p>Will never run if {@link #isInitialized()} is not implemented.</p>
*
* @param level the level the block entity exists in
* @param state the current block state
* @param pos the world position of the block entity

View File

@@ -33,13 +33,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
public class RocketAssemblerBlockEntity extends BlockEntity implements TickableBlockEntity {
Direction facing;
BlockPos padScanStart = BlockPos.ZERO;
private PadInfo padBounds;
RocketEntity lastRocket;
private @Nullable PartitionData data;
@@ -296,14 +297,17 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB
if (level == null) return null;
RocketStructure structure = scan();
RocketEntity rocket = null;
if (lastRocket != null)
lastRocket.disassemble();
var rockets = getRocketsInPad();
if (rockets.size() == 1) rocket = rockets.getFirst();
if (rocket != null)
rocket.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;
}
@@ -373,6 +377,38 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB
return s.is(TOWER_BLOCK);
}
public @NotNull List<RocketEntity> getRocketsInPad() {
if (level == null || padBounds == null) return List.of();
AABB padBox = new AABB(
padBounds.min().getX(),
padBounds.min().getY(),
padBounds.min().getZ(),
padBounds.max().getX() + 1,
padBounds.max().getY() + 1,
padBounds.max().getZ() + 1
);
var rockets = new ArrayList<>(level.getEntitiesOfClass(RocketEntity.class, padBox.inflate(0.2)));
List<RocketEntity> found = new java.util.ArrayList<>(List.of());
for (RocketEntity rocket : rockets) {
AABB rocketBox = rocket.getBoundingBox();
if (!isFullyInside(padBox, rocketBox)) continue;
found.add(rocket);
}
return found;
}
private static boolean isFullyInside(AABB outer, AABB inner) {
return inner.minX >= outer.minX && inner.maxX <= outer.maxX
&& inner.minY >= outer.minY && inner.maxY <= outer.maxY
&& inner.minZ >= outer.minZ && inner.maxZ <= outer.maxZ;
}
@Override
protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
super.saveAdditional(tag, registries);

View File

@@ -0,0 +1,61 @@
package net.xevianlight.aphelion.block.entity.custom;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import net.xevianlight.aphelion.core.init.ModDimensions;
import net.xevianlight.aphelion.core.saveddata.SpacePartitionSavedData;
import net.xevianlight.aphelion.core.saveddata.types.PartitionData;
import org.jetbrains.annotations.Nullable;
public class StationFlightComputerBlockEntity extends BlockEntity implements TickableBlockEntity {
public StationFlightComputerBlockEntity(BlockPos pos, BlockState blockState) {
super(ModBlockEntities.STATION_FLIGHT_COMPUTER_BLOCK_ENTITY.get(), pos, blockState);
}
protected PartitionData data;
private boolean isInitialized = false;
@Override
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {
}
@Override
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
if (data == null) return;
data.setTraveling(true);
}
public @Nullable PartitionData getData() {
return data;
}
@Override
public void firstTick(Level level, BlockState state, BlockPos pos) {
if (level.isClientSide()) return;
if (level instanceof ServerLevel serverLevel) {
if (serverLevel.dimension() == ModDimensions.SPACE) {
data = SpacePartitionSavedData.get(serverLevel).getDataForBlockPos(pos);
}
}
isInitialized = true;
}
protected boolean setTraveling(boolean value) {
if (data == null) return false;
data.setTraveling(value);
return true;
}
@Override
public boolean isInitialized() {
return isInitialized;
}
}

View File

@@ -0,0 +1,90 @@
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.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.level.block.state.BlockState;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
import net.neoforged.neoforge.fluids.capability.templates.FluidTank;
import net.xevianlight.aphelion.block.entity.custom.base.StationEngineBlockEntity;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import net.xevianlight.aphelion.core.init.ModFluidTags;
public class StationRocketEngineBlockEntity extends StationEngineBlockEntity {
/// Seconds to travel 1 AU
private final double SECONDS_PER_AU = 60;
/// AU per tick
private final double SPEED = 1/(SECONDS_PER_AU*20);
/// Fuel consumption per tick in millibuckets
private static final int FUEL_CONSUMPTION = 10;
private FluidTank tank = new FluidTank(
2000,
fluidStack -> fluidStack.is(ModFluidTags.ROCKET_FUEL)
);
@Override
public double getTravelSpeed() {
return SPEED;
}
public IFluidHandler getFluidStorage(Direction direction) {
return tank;
}
public StationRocketEngineBlockEntity(BlockPos pos, BlockState blockState) {
super(ModBlockEntities.STATION_ROCKET_ENGINE_BLOCK_ENTITY.get(), pos, blockState);
}
@Override
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
super.serverTick(level, time, state, pos);
burn();
}
private void burn() {
if (data == null)
return;
if (data.getDestination() != null && data.isTraveling()) {
if (!tank.isEmpty() && tank.getFluid().is(ModFluidTags.ROCKET_FUEL) && tank.getFluidAmount() >= FUEL_CONSUMPTION) { // has enough fuel?
if (data.travel(getTravelSpeed()))
tank.drain(FUEL_CONSUMPTION, IFluidHandler.FluidAction.EXECUTE);
} else {
// not enough fuel
}
}
}
@Override
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.saveAdditional(tag, registries);
tag.put("fluid", tank.writeToNBT(registries, new CompoundTag()));
}
@Override
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
if (tag.contains("fluid")) {
tank.readFromNBT(registries, tag.getCompound("fluid"));
}
}
@Override
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
CompoundTag tag = new CompoundTag();
saveAdditional(tag, registries);
return tag;
}
@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}
}

View File

@@ -1,4 +1,4 @@
package net.xevianlight.aphelion.block.custom.base;
package net.xevianlight.aphelion.block.entity.custom.base;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
@@ -7,6 +7,7 @@ import net.minecraft.world.level.Level;
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.block.custom.base.TickableBlockEntity;
import net.xevianlight.aphelion.core.init.ModDimensions;
import net.xevianlight.aphelion.core.saveddata.SpacePartitionSavedData;
import net.xevianlight.aphelion.core.saveddata.types.PartitionData;
@@ -16,7 +17,7 @@ import javax.annotation.Nullable;
public abstract class StationEngineBlockEntity extends BlockEntity implements TickableBlockEntity {
private boolean isInitialized = false;
private @Nullable PartitionData data;
protected @Nullable PartitionData data;
/**
* The travel speed in AU/tick.
@@ -32,31 +33,9 @@ public abstract class StationEngineBlockEntity extends BlockEntity implements Ti
}
/**
* Handles station travel logic for this engine.
*
* <p>If the associated station is currently traveling, this method advances
* its movement using the value returned by {@link #getTravelSpeed()}.</p>
*
* <p>Subclasses may override this method to add additional server-side behavior.
* When doing so, {@code super.serverTick(...)} should be called to preserve
* the default travel logic.</p>
*
* <p>This method is invoked once per server tick.</p>
*
* @param level the server level the block entity exists in
* @param time the current tick time offset used for scheduling
* @param state the current block state
* @param pos the world position of the block entity
*/
@Override
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
double speed = getTravelSpeed();
if (data != null) {
if (data.isTraveling()) {
data.travel(speed);
}
}
}
@Override
@@ -70,6 +49,7 @@ public abstract class StationEngineBlockEntity extends BlockEntity implements Ti
if (level instanceof ServerLevel serverLevel) {
if (serverLevel.dimension() == ModDimensions.SPACE) {
data = SpacePartitionSavedData.get(serverLevel).getDataForBlockPos(pos);
data.addEngine(pos);
}
}
isInitialized = true;

View File

@@ -49,11 +49,16 @@ public class AphelionDebugOverlay {
// Left side of F3
event.getLeft().add("");
event.getLeft().add("Aphelion:");
event.getLeft().add(" Orbit: " + orbitId);
event.getLeft().add(" Orbit: " + PartitionClientState.lastData().getOrbit());
// event.getLeft().add(" Sky: " + rendererSummary);
event.getLeft().add(" Station: " + x + " " + z + " ID: " + SpacePartitionSavedData.pack(x,z));
event.getLeft().add(" Station Destination:" + PartitionClientState.lastData().getDestination());
event.getLeft().add(" Station Owner:" + PartitionClientState.lastData().getOwner());
event.getLeft().add(" Station Destination: " + PartitionClientState.lastData().getDestination());
event.getLeft().add(" Station Owner: " + PartitionClientState.lastData().getOwner());
event.getLeft().add(" Station Engines: " + PartitionClientState.lastData().getEngines().toArray().length);
event.getLeft().add(" Station Landing Pads: " + PartitionClientState.lastData().getLandingPadContollersAsArray().length);
event.getLeft().add(" Station Traveling: " + PartitionClientState.lastData().isTraveling());
event.getLeft().add(" Station Trip Distance AU: " + PartitionClientState.lastData().getTripDistanceAU());
event.getLeft().add(" Station Distance Traveled AU: " + PartitionClientState.lastData().getDistanceTraveledAU());
var server = mc.getSingleplayerServer();
ServerLevel singlePlayerLevel;
if (server != null) {

View File

@@ -75,12 +75,10 @@ public class SpaceSkyEffects extends DimensionSpecialEffects {
// int px = PartitionClientState.pxOr(0);
// int py = PartitionClientState.pyOr(0);
var data = ResourceLocation.parse(PartitionClientState.idOrUnknown());
// var partitionData = SpacePartitionSavedData.get(serverLevel).getOrbitForPartition((int) x, (int) z);
if (data != null) return data;
return ResourceLocation.parse(PartitionClientState.idOrUnknown());
return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/default");
}
}

View File

@@ -4,6 +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.StationRocketEngineBlockEntity;
import net.xevianlight.aphelion.block.dummy.entity.VAFMultiblockDummyBlockEntity;
import net.xevianlight.aphelion.block.entity.custom.*;
@@ -51,4 +52,14 @@ public class ModBlockEntities {
BLOCK_ENTITIES.register("rocket_assembler_block_entity", () -> BlockEntityType.Builder.of(
RocketAssemblerBlockEntity::new, ModBlocks.ROCKET_ASSEMBLER.get()).build(null)
);
public static final Supplier<BlockEntityType<StationRocketEngineBlockEntity>> STATION_ROCKET_ENGINE_BLOCK_ENTITY =
BLOCK_ENTITIES.register("station_rocket_engine_block_entity", () -> BlockEntityType.Builder.of(
StationRocketEngineBlockEntity::new, ModBlocks.STATION_ROCKET_ENGINE.get()).build(null)
);
public static final Supplier<BlockEntityType<StationFlightComputerBlockEntity>> STATION_FLIGHT_COMPUTER_BLOCK_ENTITY =
BLOCK_ENTITIES.register("station_flight_computer_block_entity", () -> BlockEntityType.Builder.of(
StationFlightComputerBlockEntity::new, ModBlocks.STATION_FLIGHT_COMPUTER_BLOCK.get()).build(null)
);
}

View File

@@ -10,15 +10,19 @@ import net.xevianlight.aphelion.block.dummy.VAFMultiblockDummyBlock;
public class ModBlocks {
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(Aphelion.MOD_ID);
public static final DeferredBlock<Block> TEST_BLOCK = BLOCKS.register("test_block", () -> new TestBlock(TestBlock.getProperties()));
public static final DeferredBlock<Block> BLOCK_STEEL = BLOCKS.register("block_steel", () -> new BlockSteel(BlockSteel.getProperties()));
public static final DeferredBlock<Block> LAUNCH_PAD = BLOCKS.register("launch_pad", () -> new LaunchPad(LaunchPad.getProperties()));
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()));
public static final DeferredBlock<Block> VAF_MULTIBLOCK_DUMMY_BLOCK = BLOCKS.register("vaf_dummy_block", () -> new VAFMultiblockDummyBlock(VAFMultiblockDummyBlock.getProperties()));
public static final DeferredBlock<Block> TEST_BLOCK = BLOCKS.register("test_block", () -> new TestBlock(TestBlock.getProperties()));
public static final DeferredBlock<Block> BLOCK_STEEL = BLOCKS.register("block_steel", () -> new BlockSteel(BlockSteel.getProperties()));
public static final DeferredBlock<Block> LAUNCH_PAD = BLOCKS.register("launch_pad", () -> new LaunchPad(LaunchPad.getProperties()));
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()));
public static final DeferredBlock<Block> VAF_MULTIBLOCK_DUMMY_BLOCK = BLOCKS.register("vaf_dummy_block", () -> new VAFMultiblockDummyBlock(VAFMultiblockDummyBlock.getProperties()));
public static final DeferredBlock<Block> OXYGEN_TEST_BLOCK = BLOCKS.register("oxygen_test_block", () -> new OxygenTestBlock(OxygenTestBlock.getProperties()));
public static final DeferredBlock<Block> ROCKET_ASSEMBLER = BLOCKS.register("rocket_assembler", () -> new RocketAssembler(RocketAssembler.getProperties()));
public static final DeferredBlock<Block> ROCKET_SEAT = BLOCKS.register("rocket_seat", () -> new RocketSeat(RocketSeat.getProperties()));
public static final DeferredBlock<Block> STATION_ROCKET_ENGINE = BLOCKS.register("station_rocket_engine", () -> new StationRocketEngineBlock(StationRocketEngineBlock.getProperties()));
public static final DeferredBlock<Block> BASIC_ROCKET_FUEL_TANK = BLOCKS.register("basic_rocket_fuel_tank", () -> new BasicRocketFuelTank(BasicRocketFuelTank.getProperties()));
public static final DeferredBlock<Block> BASIC_ROCKET_CONTAINER = BLOCKS.register("basic_rocket_container", () -> new BasicRocketContainer(BasicRocketContainer.getProperties()));
public static final DeferredBlock<Block> STATION_FLIGHT_COMPUTER_BLOCK = BLOCKS.register("station_flight_computer", () -> new StationFlightComputerBlock(StationFlightComputerBlock.getProperties()));
}

View File

@@ -28,6 +28,7 @@ public class ModCreativeTabs {
output.accept(ModItems.INGOT_NEODYMIUM);
output.accept(ModItems.INGOT_IRIDIUM);
output.accept(ModFluids.OIL_BUCKET);
output.accept(ModFluids.ROCKET_FUEL_BUCKET);
output.accept(ModItems.MUSIC_DISC_BIT_SHIFT);
}).build());

View File

@@ -0,0 +1,18 @@
package net.xevianlight.aphelion.core.init;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.material.Fluid;
public class ModFluidTags {
public static final TagKey<Fluid> ROCKET_FUEL = create("rocket_fuel");
private static TagKey<Fluid> create(String name) {
return TagKey.create(Registries.FLUID, ResourceLocation.withDefaultNamespace(name));
}
public static TagKey<Fluid> create(ResourceLocation name) {
return TagKey.create(Registries.FLUID, name);
}
}

View File

@@ -38,5 +38,8 @@ public static final DeferredItem<Item> MUSIC_DISC_BIT_SHIFT = ITEMS.register("mu
public static final DeferredItem<BlockItem> LAUNCH_PAD = ITEMS.register("launch_pad", () -> new BlockItem(ModBlocks.LAUNCH_PAD.get(), LaunchPad.getItemProperties()));
public static final DeferredItem<BlockItem> ROCKET_ASSEMBLER = ITEMS.register("rocket_assembler", () -> new BlockItem(ModBlocks.ROCKET_ASSEMBLER.get(), RocketAssembler.getItemProperties()));
public static final DeferredItem<BlockItem> ROCKET_SEAT = ITEMS.register("rocket_seat", () -> new BlockItem(ModBlocks.ROCKET_SEAT.get(), RocketSeat.getItemProperties()));
public static final DeferredItem<BlockItem> STATION_ROCKET_ENGINE = ITEMS.register("station_rocket_engine", () -> new BlockItem(ModBlocks.STATION_ROCKET_ENGINE.get(), StationRocketEngineBlock.getItemProperties()));
public static final DeferredItem<BlockItem> BASIC_ROCKET_FUEL_TANK = ITEMS.register("basic_rocket_fuel_tank", () -> new BlockItem(ModBlocks.BASIC_ROCKET_FUEL_TANK.get(), BasicRocketFuelTank.getItemProperties()));
public static final DeferredItem<BlockItem> BASIC_ROCKET_CONTAINER = ITEMS.register("basic_rocket_container", () -> new BlockItem(ModBlocks.BASIC_ROCKET_CONTAINER.get(), BasicRocketContainer.getItemProperties()));
// public static final DeferredItem<BlockItem> VAF_MULTIBLOCK_DUMMY_BLOCK = ITEMS.register("vaf_multiblock_dummy_block", () -> new BlockItem(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get(), VAFMultiblockDummyBlock.getItemProperties()));
}

View File

@@ -105,7 +105,7 @@ public class SpacePartitionSavedData extends SavedData {
e.putBoolean("Traveling", pd.isTraveling());
e.putDouble("DistanceTraveled", pd.getDistanceTraveledAU());
e.putDouble("DistanceToDest", pd.getTripDistanceAU());
e.putDouble("DistanceToDest", pd.recalculateTripDistAU());
if (pd.getOwner() != null) {
e.putUUID("Owner", pd.getOwner());

View File

@@ -6,6 +6,7 @@ import net.minecraft.core.UUIDUtil;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceLocation;
import net.xevianlight.aphelion.planet.PlanetCache;
import net.xevianlight.aphelion.util.BigCodec;
import org.jetbrains.annotations.Nullable;
@@ -26,6 +27,11 @@ public class PartitionData {
private UUID owner;
private List<BlockPos> landingPadControllers;
private List<BlockPos> engines;
private double currentOrbitDistanceAU;
public PartitionData() {
}
public PartitionData(@Nullable ResourceLocation orbit) {
this.orbit = orbit;
@@ -36,7 +42,7 @@ public class PartitionData {
this.generated = false;
this.owner = null;
this.landingPadControllers = List.of();
this.engines = List.of();
this.engines = new ArrayList<>(List.of());
}
public PartitionData(PartitionData other) {
@@ -68,7 +74,7 @@ public class PartitionData {
PartitionData::getDistanceTraveledAU,
ByteBufCodecs.DOUBLE,
PartitionData::getTripDistanceAU,
PartitionData::recalculateTripDistAU,
ByteBufCodecs.optional(UUIDUtil.STREAM_CODEC),
d -> Optional.ofNullable(d.getOwner()),
@@ -102,6 +108,8 @@ public class PartitionData {
public void setOrbit(@Nullable ResourceLocation orbit) {
this.orbit = orbit;
recalculateTripDistAU();
distanceTraveledAU = 0;
}
public @Nullable ResourceLocation getDestination() {
@@ -110,6 +118,8 @@ public class PartitionData {
public void setDestination(@Nullable ResourceLocation destination) {
this.destination = destination;
recalculateTripDistAU();
distanceTraveledAU = 0;
}
public boolean isTraveling() {
@@ -128,6 +138,19 @@ public class PartitionData {
this.distanceTraveledAU = distanceTraveledAU;
}
public double recalculateTripDistAU() {
var currentPlanet = PlanetCache.getByOrbitOrNull(orbit);
if (currentPlanet == null) {
return -1;
}
var destPlanet = PlanetCache.getOrDefault(destination);
var dist = destPlanet.orbitDistance() - currentPlanet.orbitDistance();
this.tripDistanceAU = dist;
return dist;
}
public double getTripDistanceAU() {
return tripDistanceAU;
}
@@ -146,9 +169,20 @@ public class PartitionData {
* distance is set to exactly {@code tripDistanceAU}.</p>
*
* @param distance the distance to advance in astronomical units (AU)
* @return {@code true} when we arrive at our destination, {@code false} otherwise.
*/
public void travel(double distance) {
distanceTraveledAU = Math.min(distanceTraveledAU + distance, tripDistanceAU);
public boolean travel(double distance) {
if (distanceTraveledAU + distance > tripDistanceAU) {
distanceTraveledAU = tripDistanceAU;
var destinationPlanet = PlanetCache.getOrNull(destination);
if (destinationPlanet != null) {
setOrbit(destinationPlanet.orbit().location());
}
return false;
} else {
distanceTraveledAU += distance;
return true;
}
}
public boolean isGenerated() {
@@ -223,14 +257,40 @@ public class PartitionData {
return landingPadControllers.remove(pos);
}
/**
* Returns a defensive copy of the world positions of all engines tracked by this partition.
*
* <p>This method returns only the stored {@link BlockPos} locations of known engines,
* not the engine instances or their corresponding block entities. To interact with an
* engine, retrieve the block entity from the world using the returned positions.</p>
*
* <p>It is not guaranteed that an engine exists at every returned position. If changes
* fail to synchronize with this partition, the stored data may become inaccurate.
* Always verify that the block entity at a given position is an engine before use.</p>
*
* <p>The returned list is a defensive copy and may be modified without affecting the
* underlying partition data. To persist changes, use {@code setEngines(...)}.</p>
*
* @return a mutable list containing the tracked engine positions
*/
public List<BlockPos> getEngines() {
return engines;
return new ArrayList<>(engines);
}
public void setEngines(List<BlockPos> engines) {
this.engines = engines;
}
/**
* Adds an engine at the specified world position.
*
* <p>If an engine does not already exist at the given position, it is added
* to the internal collection and the method returns {@code true}. If an engine
* is already present at that position, no changes are made.</p>
*
* @param pos the world position of the engine to add
* @return {@code true} if the engine was added, {@code false} if it already existed
*/
public boolean addEngine(BlockPos pos) {
if (!engines.contains(pos)) {
engines.add(pos);

View File

@@ -6,6 +6,7 @@ import net.minecraft.data.tags.FluidTagsProvider;
import net.minecraft.tags.FluidTags;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModFluidTags;
import net.xevianlight.aphelion.fluid.ModFluids;
import org.jetbrains.annotations.Nullable;
@@ -22,5 +23,7 @@ public class ModFluidTagsProvider extends FluidTagsProvider {
// tag(FluidTags.LAVA)
// .add(ModFluids.SOURCE_OIL_FLUID.get())
// .add(ModFluids.FLOWING_OIL_FLUID.get());
tag(ModFluidTags.ROCKET_FUEL)
.add(ModFluids.ROCKET_FUEL.get());
}
}

View File

@@ -44,6 +44,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.UUID;
public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpawn {
@@ -108,7 +109,6 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
};
}
public static RocketEntity spawnRocket(Level level, BlockPos pos, RocketStructure structure) {
if (level.isClientSide) return null;
@@ -122,12 +122,22 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
0.0f
);
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);
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);
// Fully initialize structure and containers
rocket.setStructure(structure);
if (rocket.INVENTORY.getSlots() > 0)
rocket.INVENTORY.insertItem(0, new ItemStack(Items.DIAMOND), false);
if (rocket.FUEL_TANK.getCapacity() != 0)
rocket.FUEL_TANK.setFluid(new FluidStack(ModFluids.OIL.get(), 1000));
if (rocket.FLUID_STORAGE.getCapacity() != 0)
rocket.FLUID_STORAGE.setFluid(FluidStack.EMPTY);
level.addFreshEntity(rocket);
return rocket;
}
@@ -166,6 +176,9 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
if (!level().isClientSide) {
if (INVENTORY.getSlots() > 0)
INVENTORY.insertItem(0, new ItemStack(Items.DIAMOND, 1), false);
switch (getPhase()) {
case IDLE, LANDED -> tickIdle();
case PREPARE -> tickPrepare();
@@ -184,7 +197,10 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
}
move(MoverType.SELF, getDeltaMovement());
// Catch ANY edge cases which may cause a crash trying to move an entity as its chunk is unloading
if (!this.isRemoved() && this.isAlive() && level().hasChunkAt(blockPosition())) {
move(MoverType.SELF, getDeltaMovement());
}
}
private void tickIdle() {
@@ -393,7 +409,7 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
if (tag.contains("RocketStructure")) {
CompoundTag rocketTag = tag.getCompound("RocketStructure");
structure.load(rocketTag);
recalculateCapacitiesFromStructure();
// recalculateCapacitiesFromStructure();
// Immediately apply correct bbox on load (server + client)
double x = getX(), y = getY(), z = getZ();
@@ -590,6 +606,7 @@ public class RocketEntity extends VehicleEntity implements IEntityWithComplexSpa
public boolean disassemble() {
if (level().isClientSide) return false;
if (!(level() instanceof ServerLevel server)) return false;
Aphelion.LOGGER.info("Disassemble called for rocket: " + getId());
// 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().

View File

@@ -8,13 +8,13 @@ import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.registration.HandlerThread;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.entity.custom.StationRocketEngineBlockEntity;
import net.xevianlight.aphelion.block.dummy.entity.BaseMultiblockDummyBlockEntity;
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;
@@ -25,15 +25,20 @@ public class ModBusEvents {
@SubscribeEvent
public static void registerCapabilities(RegisterCapabilitiesEvent event) {
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);
// 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());
event.registerBlockEntity(Capabilities.FluidHandler.BLOCK, ModBlockEntities.STATION_ROCKET_ENGINE_BLOCK_ENTITY.get(), StationRocketEngineBlockEntity::getFluidStorage);
}
@SubscribeEvent

View File

@@ -7,7 +7,11 @@ import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.common.SoundAction;
import net.neoforged.neoforge.common.SoundActions;
import net.neoforged.neoforge.fluids.FluidType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,6 +57,17 @@ public class BaseFluidType extends FluidType {
this.fogEnd = fogEnd;
}
@Override
public @Nullable SoundEvent getSound(SoundAction action) {
if (action == SoundActions.BUCKET_FILL) {
return SoundEvents.BUCKET_FILL;
}
if (action == SoundActions.BUCKET_EMPTY) {
return SoundEvents.BUCKET_EMPTY;
}
return super.getSound(action);
}
public IClientFluidTypeExtensions getClientFluidTypeExtensions() {
return new IClientFluidTypeExtensions() {
@Override

View File

@@ -8,23 +8,51 @@ import net.neoforged.neoforge.registries.NeoForgeRegistries;
import net.xevianlight.aphelion.Aphelion;
import org.joml.Vector3f;
import java.awt.*;
import java.util.function.Supplier;
public class ModFluidTypes {
public static final ResourceLocation WATER_STILL_RL = ResourceLocation.parse("block/water_still");
public static final ResourceLocation WATER_FLOWING_RL = ResourceLocation.parse("block/water_flow");
public static final ResourceLocation WATER_OVERLAY_RL = ResourceLocation.parse("block/water_overlay");
public static final ResourceLocation WATER_STILL_RL =
ResourceLocation.fromNamespaceAndPath("minecraft", "block/water_still");
public static final ResourceLocation WATER_FLOWING_RL =
ResourceLocation.fromNamespaceAndPath("minecraft", "block/water_flow");
public static final ResourceLocation WATER_OVERLAY_RL =
ResourceLocation.fromNamespaceAndPath("minecraft", "block/water_overlay");
static final Color oilColor = new Color(10, 10, 10, 255);
static final Color rocketFuelColor = new Color(73, 59, 28, 255);
public static final DeferredRegister<FluidType> FLUID_TYPES =
DeferredRegister.create(NeoForgeRegistries.Keys.FLUID_TYPES, Aphelion.MOD_ID);
public static final Supplier<FluidType> OIL_FLUID_TYPE = registerFluidType("oil",
new BaseFluidType(WATER_STILL_RL, WATER_FLOWING_RL, WATER_OVERLAY_RL, 0xFF101010,
new Vector3f(10f / 255f, 10f / 255f, 10f / 255f),
FluidType.Properties.create().canDrown(true), 0f, 2f
new BaseFluidType(
WATER_STILL_RL,
WATER_FLOWING_RL,
WATER_OVERLAY_RL,
oilColor.getRGB(),
colToVec(oilColor),
FluidType.Properties.create().canDrown(true),
0f,
0.5f
)
);
public static final Supplier<FluidType> ROCKET_FUEL_FLUID_TYPE = registerFluidType("rocket_fuel",
new BaseFluidType(
WATER_STILL_RL,
WATER_FLOWING_RL,
WATER_OVERLAY_RL,
rocketFuelColor.getRGB(),
colToVec(rocketFuelColor),
FluidType.Properties.create().canDrown(true),
0f,
2f)
);
private static Supplier<FluidType> registerFluidType(String name, FluidType fluidType) {
return FLUID_TYPES.register(name, () -> fluidType);
}
@@ -32,4 +60,8 @@ public class ModFluidTypes {
public static void register(IEventBus eventBus) {
FLUID_TYPES.register(eventBus);
}
public static Vector3f colToVec (Color color) {
return new Vector3f(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f);
}
}

View File

@@ -24,13 +24,29 @@ public class ModFluids {
public static final DeferredRegister<Fluid> FLUIDS =
DeferredRegister.create(BuiltInRegistries.FLUID, Aphelion.MOD_ID);
public static final Supplier<FlowingFluid> ROCKET_FUEL = FLUIDS.register("rocket_fuel",
() -> new BaseFlowingFluid.Source(ModFluids.ROCKET_FUEL_PROPERTIES));
public static final Supplier<FlowingFluid> FLOWING_ROCKET_FUEL = FLUIDS.register("flowing_rocket_fuel",
() -> new BaseFlowingFluid.Flowing(ModFluids.ROCKET_FUEL_PROPERTIES));
public static final DeferredBlock<LiquidBlock> ROCKET_FUEL_BLOCK = ModBlocks.BLOCKS.register("rocket_fuel",
() -> new LiquidBlock(ModFluids.ROCKET_FUEL.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable()));
public static final DeferredItem<Item> ROCKET_FUEL_BUCKET = ModItems.ITEMS.registerItem("rocket_fuel_bucket",
properties -> new BucketItem(ModFluids.ROCKET_FUEL.get(), properties.stacksTo(1).craftRemainder(Items.BUCKET)));
public static final BaseFlowingFluid.Properties ROCKET_FUEL_PROPERTIES = new BaseFlowingFluid.Properties(
ModFluidTypes.ROCKET_FUEL_FLUID_TYPE, ROCKET_FUEL, FLOWING_ROCKET_FUEL)
.slopeFindDistance(2).levelDecreasePerBlock(2).tickRate(10)
.block(ModFluids.ROCKET_FUEL_BLOCK).bucket(ModFluids.ROCKET_FUEL_BUCKET);
public static final Supplier<FlowingFluid> OIL = FLUIDS.register("oil",
() -> new BaseFlowingFluid.Source(ModFluids.OIL_PROPERTIES));
public static final Supplier<FlowingFluid> FLOWING_OIL = FLUIDS.register("flowing_oil",
() -> new BaseFlowingFluid.Flowing(ModFluids.OIL_PROPERTIES));
public static final DeferredBlock<LiquidBlock> OIL_BLOCK = ModBlocks.BLOCKS.register("oil",
() -> new LiquidBlock(ModFluids.OIL.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable()));
() -> new LiquidBlock(ModFluids.OIL.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable()));
public static final DeferredItem<Item> OIL_BUCKET = ModItems.ITEMS.registerItem("oil_bucket",
properties -> new BucketItem(ModFluids.OIL.get(), properties.stacksTo(1).craftRemainder(Items.BUCKET)));

View File

@@ -9,7 +9,6 @@ import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.profiling.ProfilerFiller;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.client.dimension.DimensionRenderer;
import net.xevianlight.aphelion.util.Constants;
import java.util.HashMap;

View File

@@ -0,0 +1,12 @@
package net.xevianlight.aphelion.planet;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
public record Orbit(
int temp
) {
public static final Codec<Orbit> CODEC = RecordCodecBuilder.create(inst -> inst.group(
Codec.INT.fieldOf("temp").forGetter(Orbit::temp)
).apply(inst, Orbit::new));
}

View File

@@ -7,8 +7,9 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import net.xevianlight.aphelion.util.registries.ModRegistries;
public record Planet(
public record Planet (
ResourceKey<Level> dimension,
ResourceKey<Orbit> orbit,
double orbitDistance,
ResourceKey<StarSystem> system,
boolean oxygen,
@@ -16,6 +17,7 @@ public record Planet(
) {
public static final Codec<Planet> CODEC = RecordCodecBuilder.create(inst -> inst.group(
ResourceKey.codec(Registries.DIMENSION).fieldOf("dimension").forGetter(Planet::dimension),
ResourceKey.codec(ModRegistries.ORBIT).fieldOf("orbit").forGetter(Planet::orbit),
Codec.DOUBLE.fieldOf("orbit_distance").forGetter(Planet::orbitDistance),
ResourceKey.codec(ModRegistries.STAR_SYSTEM).fieldOf("star_system").forGetter(Planet::system),
Codec.BOOL.fieldOf("oxygen").forGetter(Planet::oxygen),

View File

@@ -6,6 +6,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.util.registries.ModRegistries;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
@@ -17,6 +18,7 @@ public final class PlanetCache {
public static final Planet DEFAULT = new Planet(
ResourceKey.create(Registries.DIMENSION, ResourceLocation.withDefaultNamespace("overworld")),
ResourceKey.create(ModRegistries.ORBIT, Aphelion.id("orbit/overworld")),
1,
ResourceKey.create(ModRegistries.STAR_SYSTEM, Aphelion.id("sol")),
true,
@@ -48,6 +50,17 @@ public final class PlanetCache {
return PLANETS.getOrDefault(id, DEFAULT);
}
public static @Nullable Planet getOrNull(ResourceLocation id) {
return PLANETS.getOrDefault(id, null);
}
public static @Nullable Planet getByOrbitOrNull(ResourceLocation id) {
return PLANETS.values().stream()
.filter(planet -> planet.orbit().location().equals(id))
.findFirst()
.orElse(null);
}
public static Planet getByDimensionOrNull(ResourceKey<Level> dimension) {
ResourceLocation planetId = PLANET_BY_DIMENSION.get(dimension);
return planetId == null ? null : PLANETS.get(planetId);

View File

@@ -3,12 +3,14 @@ package net.xevianlight.aphelion.util.registries;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.planet.Orbit;
import net.xevianlight.aphelion.planet.Planet;
import net.xevianlight.aphelion.planet.StarSystem;
public class ModRegistries {
public static final ResourceKey<Registry<StarSystem>> STAR_SYSTEM = createRegistryKey("star_system");
public static final ResourceKey<Registry<Planet>> PLANET = createRegistryKey("planet");
public static final ResourceKey<Registry<Orbit>> ORBIT = createRegistryKey("orbit");
private static <T> ResourceKey<Registry<T>> createRegistryKey(String name) {
return ResourceKey.createRegistryKey(Aphelion.id(name));