Basic development

This commit is contained in:
XevianLight
2026-01-16 17:51:41 -07:00
parent b0131011e5
commit 48e5499ad3
119 changed files with 3613 additions and 185 deletions

View File

@@ -26,9 +26,9 @@ loader_version_range=[1,)
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
# Must match the String constant located in the main mod class annotated with @Mod.
mod_id=extreme_rocketry
mod_id=aphelion
# The human-readable display name for the mod.
mod_name=Extreme Rocketry
mod_name=Aphelion
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=GNU GPLv3
# The mod version. See https://semver.org/
@@ -36,4 +36,4 @@ mod_version=0.0.1
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
mod_group_id=net.xevianlight.extremerocketry
mod_group_id=net.xevianlight.aphelion

View File

@@ -1,8 +1,19 @@
package net.xevianlight.extreme_rocketry;
package net.xevianlight.aphelion;
import net.xevianlight.extreme_rocketry.core.init.ModBlocks;
import net.xevianlight.extreme_rocketry.core.init.ModCreativeTabs;
import net.xevianlight.extreme_rocketry.core.init.ModItems;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent;
import net.xevianlight.aphelion.client.AphelionConfig;
import net.xevianlight.aphelion.core.init.*;
import net.xevianlight.aphelion.fluid.BaseFluidType;
import net.xevianlight.aphelion.fluid.ModFluidTypes;
import net.xevianlight.aphelion.fluid.ModFluids;
import net.xevianlight.aphelion.screen.ElectricArcFurnaceScreen;
import net.xevianlight.aphelion.screen.ModMenuTypes;
import net.xevianlight.aphelion.screen.TestBlockScreen;
import org.slf4j.Logger;
import com.mojang.logging.LogUtils;
@@ -19,10 +30,10 @@ import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
// The value here should match an entry in the META-INF/neoforge.mods.toml file
@Mod(ExtremeRocketry.MOD_ID)
public class ExtremeRocketry {
@Mod(Aphelion.MOD_ID)
public class Aphelion {
// Define mod id in a common place for everything to reference
public static final String MOD_ID = "extreme_rocketry";
public static final String MOD_ID = "aphelion";
// Directly reference a slf4j logger
public static final Logger LOGGER = LogUtils.getLogger();
@@ -30,7 +41,7 @@ public class ExtremeRocketry {
// The constructor for the mod class is the first code that is run when your mod is loaded.
// FML will recognize some parameter types like IEventBus or ModContainer and pass them in automatically.
public ExtremeRocketry(IEventBus modEventBus, ModContainer modContainer) {
public Aphelion(IEventBus modEventBus, ModContainer modContainer) {
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);
@@ -39,6 +50,11 @@ public class ExtremeRocketry {
ModItems.ITEMS.register(MOD_BUS);
ModBlocks.BLOCKS.register(MOD_BUS);
ModCreativeTabs.CREATIVE_MODE_TAB.register(MOD_BUS);
ModBlockEntities.BLOCK_ENTITIES.register(MOD_BUS);
ModMenuTypes.MENUS.register(MOD_BUS);
ModFluidTypes.FLUID_TYPES.register(MOD_BUS);
ModFluids.register(MOD_BUS);
ModSounds.register(MOD_BUS);
// Register ourselves for server and other game events we are interested in.
// Note that this is necessary if and only if we want *this* class (ExtremeRocketry) to respond directly to events.
@@ -49,7 +65,7 @@ public class ExtremeRocketry {
modEventBus.addListener(this::addCreative);
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
modContainer.registerConfig(ModConfig.Type.COMMON, AphelionConfig.SPEC);
}
private void commonSetup(FMLCommonSetupEvent event) {
@@ -71,5 +87,35 @@ public class ExtremeRocketry {
public void onServerStarting(ServerStartingEvent event) {
// Do something when the server starts
LOGGER.info("HELLO from server starting");
}
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@EventBusSubscriber(modid = MOD_ID, value = Dist.CLIENT)
public static class ClientModEvents {
@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());
});
}
@SubscribeEvent
public static void onClientExtensions(RegisterClientExtensionsEvent event) {
event.registerFluidType(((BaseFluidType) ModFluidTypes.OIL_FLUID_TYPE.get()).getClientFluidTypeExtensions(), ModFluidTypes.OIL_FLUID_TYPE.get());
}
@SubscribeEvent
public static void registerBER(EntityRenderersEvent.RegisterRenderers event) {
}
@SubscribeEvent
public static void registerScreens(RegisterMenuScreensEvent event) {
event.register(ModMenuTypes.TEST_BLOCK_MENU.get(), TestBlockScreen::new);
event.register(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), ElectricArcFurnaceScreen::new);
}
}
}

View File

@@ -0,0 +1,25 @@
package net.xevianlight.aphelion.block.custom;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
public class BlockSteel extends Block {
public BlockSteel(Properties properties) {
super(properties);
}
public static Properties getProperties() {
return Properties
.of()
.sound(SoundType.NETHERITE_BLOCK)
.destroyTime(2f)
.explosionResistance(10f)
.requiresCorrectToolForDrops();
}
public static Item.Properties getItemProperties() {
return new Item.Properties();
}
}

View File

@@ -0,0 +1,93 @@
package net.xevianlight.aphelion.block.custom;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.portal.DimensionTransition;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.xevianlight.aphelion.block.entity.custom.DimensionChangerBlockEntity;
import org.jetbrains.annotations.Nullable;
public class DimensionChangerBlock extends BaseEntityBlock {
public DimensionChangerBlock(Properties properties) {
super(properties);
}
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return null;
}
public static Properties getProperties() {
return Properties
.of()
.sound(SoundType.ANVIL)
.destroyTime(2f)
.explosionResistance(10f)
.requiresCorrectToolForDrops();
}
public static Item.Properties getItemProperties() {
return new Item.Properties().stacksTo(3);
}
@Override
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof DimensionChangerBlockEntity dimensionChangerBlockEntity) {
ServerLevel sourceDim = serverPlayer.serverLevel();
ServerLevel targetDim = serverPlayer.server.getLevel(Level.NETHER);
serverPlayer.changeDimension(new DimensionTransition(
targetDim,
serverPlayer.position().multiply(
sourceDim.dimensionType().coordinateScale() / targetDim.dimensionType().coordinateScale(),
1,
sourceDim.dimensionType().coordinateScale() / targetDim.dimensionType().coordinateScale()),
Vec3.ZERO, serverPlayer.getYRot(),
serverPlayer.getXRot(),
DimensionTransition.PLAY_PORTAL_SOUND
));
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
super.tick(state, level, pos, random);
}
@Override
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new DimensionChangerBlockEntity(blockPos, blockState);
}
@Override
public RenderShape getRenderShape(BlockState pState) {
return RenderShape.MODEL;
}
@Override
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity= level.getBlockEntity(pos);
if (blockEntity instanceof DimensionChangerBlockEntity dimensionChangerBlockEntity) {
dimensionChangerBlockEntity.drops();
}
}
super.onRemove(state, level, pos, newState, movedByPiston);
}
}

View File

@@ -0,0 +1,170 @@
package net.xevianlight.aphelion.block.custom;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class ElectricArcFurnace extends BaseEntityBlock {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final BooleanProperty LIT = BlockStateProperties.LIT;
public ElectricArcFurnace(Properties properties) {
super(properties);
}
public static final MapCodec<ElectricArcFurnace> CODEC = simpleCodec(ElectricArcFurnace::new);
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}
public static Properties getProperties() {
return Properties
.of()
.sound(SoundType.METAL)
.destroyTime(2f)
.explosionResistance(10f)
.requiresCorrectToolForDrops();
}
public static Item.Properties getItemProperties() {
return new Item.Properties();
}
@Override
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
serverPlayer.openMenu(new SimpleMenuProvider(electricArcFurnaceEntity, Component.literal("Electric Arc Furnace")), pos);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
@Override
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new ElectricArcFurnaceEntity(blockPos, blockState);
}
@Override
public RenderShape getRenderShape(BlockState pState) {
return RenderShape.MODEL;
}
@Override
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity= level.getBlockEntity(pos);
if (blockEntity instanceof ElectricArcFurnaceEntity electricArcFurnaceEntity) {
electricArcFurnaceEntity.drops();
}
}
super.onRemove(state, level, pos, newState, movedByPiston);
}
public static int getRedstoneSignalFromItemHandler(@javax.annotation.Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
if (itemStackHandler == null) {
return 0;
} else {
int i = 0;
float f = 0.0F;
for(int slot : slots) {
ItemStack itemstack = itemStackHandler.getStackInSlot(slot);
if (!itemstack.isEmpty()) {
f += (float)itemstack.getCount() / (float)Math.min(itemStackHandler.getSlotLimit(slot), itemstack.getMaxStackSize());
++i;
}
}
f /= (float)slots.size();
return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
}
}
@Override
protected boolean isSignalSource(BlockState state) {
return true;
}
@Override
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return super.getSignal(state, level, pos, direction);
}
@Override
protected boolean hasAnalogOutputSignal(BlockState state) {
return true;
}
@Override
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
List<Integer> slots = new ArrayList<>();
slots.add(0);
slots.add(1);
slots.add(2);
slots.add(3);
ElectricArcFurnaceEntity electricArcFurnaceEntity = ((ElectricArcFurnaceEntity) level.getBlockEntity(pos));
return getRedstoneSignalFromItemHandler(electricArcFurnaceEntity.inventory, slots);
}
@Override
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
if (level.isClientSide) {
return null;
}
return createTickerHelper(blockEntityType, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), (level1, blockPos, blockState, electricArcFurnaceEntity) -> electricArcFurnaceEntity.tick(level1, blockPos, blockState));
}
@Override
protected BlockState rotate(BlockState state, Rotation rotation) {
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
}
@Override
protected BlockState mirror(BlockState state, Mirror mirror) {
return state.rotate(mirror.getRotation(state.getValue(FACING)));
}
@Override
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING, LIT);
}
}

View File

@@ -0,0 +1,138 @@
package net.xevianlight.aphelion.block.custom;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class TestBlock extends BaseEntityBlock {
public TestBlock(Properties properties) {
super(properties);
}
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return null;
}
public static Properties getProperties() {
return Properties
.of()
.sound(SoundType.ANVIL)
.destroyTime(2f)
.explosionResistance(10f)
.requiresCorrectToolForDrops();
}
public static Item.Properties getItemProperties() {
return new Item.Properties().stacksTo(3);
}
@Override
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof TestBlockEntity testBlockEntity) {
serverPlayer.openMenu(new SimpleMenuProvider(testBlockEntity, Component.literal("Test Block")), pos);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
@Override
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new TestBlockEntity(blockPos, blockState);
}
@Override
public RenderShape getRenderShape(BlockState pState) {
return RenderShape.MODEL;
}
@Override
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity= level.getBlockEntity(pos);
if (blockEntity instanceof TestBlockEntity testBlockEntity) {
testBlockEntity.drops();
}
}
super.onRemove(state, level, pos, newState, movedByPiston);
}
public static int getRedstoneSignalFromItemHandler(@javax.annotation.Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
if (itemStackHandler == null) {
return 0;
} else {
int i = 0;
float f = 0.0F;
for(int slot : slots) {
ItemStack itemstack = itemStackHandler.getStackInSlot(slot);
if (!itemstack.isEmpty()) {
f += (float)itemstack.getCount() / (float)Math.min(itemStackHandler.getSlotLimit(slot), itemstack.getMaxStackSize());
++i;
}
}
f /= (float)slots.size();
return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
}
}
@Override
protected boolean isSignalSource(BlockState state) {
return true;
}
@Override
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
return super.getSignal(state, level, pos, direction);
}
@Override
protected boolean hasAnalogOutputSignal(BlockState state) {
return true;
}
@Override
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
List<Integer> slots = new ArrayList<>();
slots.add(0);
TestBlockEntity testBlockEntity = ((TestBlockEntity) level.getBlockEntity(pos));
return getRedstoneSignalFromItemHandler(testBlockEntity.inventory, slots);
}
@Override
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
if (level.isClientSide) {
return null;
}
return createTickerHelper(blockEntityType, ModBlockEntities.TEST_BLOCK_ENTITY.get(), (level1, blockPos, blockState, testBlockEntity) -> testBlockEntity.tick(level1, blockPos, blockState));
}
}

View File

@@ -0,0 +1,95 @@
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.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Containers;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import net.xevianlight.aphelion.screen.TestBlockMenu;
import net.xevianlight.aphelion.util.SidedSlotHandler;
import org.jetbrains.annotations.Nullable;
public class DimensionChangerBlockEntity extends BlockEntity implements MenuProvider {
private final int SIZE = 1;
private NonNullList<ItemStack> items = NonNullList.withSize(SIZE, ItemStack.EMPTY);
public DimensionChangerBlockEntity(BlockPos pos, BlockState blockState) {
super(ModBlockEntities.DIMENSION_CHANGER_BLOCK_ENTITY.get(), pos, blockState);
}
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
@Override
protected void onContentsChanged(int slot) {
setChanged();
if(!level.isClientSide()) {
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
}
};
public void sendUpdate() {
setChanged();
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
private final IItemHandler topHandler = new SidedSlotHandler(inventory, new int[]{0}, true, false);
private final IItemHandler bottomHandler = new SidedSlotHandler(inventory, new int[]{0}, false, true);
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
public IItemHandler getItemHandler(Direction direction) {
if (direction == Direction.UP) return topHandler;
if (direction == Direction.DOWN) return bottomHandler;
if (direction == null) return jadeHandler;
return null;
}
public ItemStackHandler getInventory() {
return inventory;
}
public void drops() {
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
for(int i = 0; i < inventory.getSlots(); i++) {
inv.setItem(i, inventory.getStackInSlot(i));
}
Containers.dropContents(this.level, this.worldPosition, inv);
}
@Override
protected void saveAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
pTag.put("inventory", inventory.serializeNBT(pRegistries));
super.saveAdditional(pTag, pRegistries);
}
@Override
protected void loadAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
super.loadAdditional(pTag, pRegistries);
inventory.deserializeNBT(pRegistries, pTag.getCompound("inventory"));
}
@Override
public Component getDisplayName() {
return null;
}
@Override
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
return new TestBlockMenu(i, inventory, this);
}
}

View File

@@ -0,0 +1,311 @@
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.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.Containers;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.energy.EnergyStorage;
import net.neoforged.neoforge.energy.IEnergyStorage;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
import net.xevianlight.aphelion.block.entity.energy.ModEnergyUtil;
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
import net.xevianlight.aphelion.util.SidedSlotHandler;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider {
private final int SIZE = 4;
private int ENERGY_CAPACITY = 64000;
private int MAX_TRANSFER = 320;
private int progress = 0;
private int maxProgress = 100;
private final int DEFAULT_MAX_PROGRESS = 100;
private final ContainerData data;
private int Blasting_ENERGY_COST = 20;
private final int INPUT_SLOT = 0;
private final int SECONDARY_INPUT_SLOT = 1;
private final int OUTPUT_SLOT = 2;
private final int ENERGY_SLOT = 3;
public ElectricArcFurnaceEntity(BlockPos pos, BlockState blockState) {
super(ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), pos, blockState);
this.data = new ContainerData() {
@Override
public int get(int index) {
return switch (index) {
case 0 -> ElectricArcFurnaceEntity.this.progress;
case 1 -> ElectricArcFurnaceEntity.this.maxProgress;
default -> 0;
};
}
@Override
public void set(int index, int pValue) {
switch (index) {
case 0: ElectricArcFurnaceEntity.this.progress = pValue;
case 1: ElectricArcFurnaceEntity.this.maxProgress = pValue;
}
}
@Override
public int getCount() {
return 2;
}
};
}
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
@Override
protected void onContentsChanged(int slot) {
setChanged();
if(!level.isClientSide()) {
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
}
// @Override
// public boolean isItemValid(int slot, ItemStack stack) {
// if (slot == ENERGY_SLOT) {
// var capability = stack.getCapability(Capabilities.EnergyStorage.ITEM);
// return capability != null;
// }
// return super.isItemValid(slot, stack);
// }
};
public void tick(Level level, BlockPos pos, BlockState blockState) {
if (inventory.getStackInSlot(SECONDARY_INPUT_SLOT).isEmpty()) {
if (hasFurnaceRecipe(INPUT_SLOT) && hasEnoughEnergyToCraft(Blasting_ENERGY_COST)) {
progress++;
useEnergyForBlasting();
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, true));
setChanged(level, pos, blockState);
if (hasCraftingFinished()) {
outputBlastingResult(INPUT_SLOT, OUTPUT_SLOT);
resetProgress();
}
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(Blasting_ENERGY_COST)) {
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
setChanged(level, pos, blockState);
progress = progress > 0 ? progress - 1 : 0;
} else {
resetProgress();
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
setChanged(level, pos, blockState);
}
} else {
resetProgress();
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
setChanged(level, pos, blockState);
}
chargeFromItem();
}
private void chargeFromItem() {
ItemStack stack;
try {
stack = inventory.getStackInSlot(ENERGY_SLOT);
if (stack.isEmpty()) return;
IEnergyStorage itemEnergy = stack.getCapability(Capabilities.EnergyStorage.ITEM);
if (itemEnergy == null || !itemEnergy.canExtract()) return;
int freeCapacity = ENERGY_STORAGE.getMaxEnergyStored() - ENERGY_STORAGE.getEnergyStored();
if (freeCapacity <= 0) return;
int maxMove = Math.min(MAX_TRANSFER, freeCapacity);
// Simulate extraction first
int canExtract = itemEnergy.extractEnergy(maxMove, true);
if (canExtract <= 0) return;
// Receive into block (simulate then execute is safest)
int canReceive = ENERGY_STORAGE.receiveEnergy(canExtract, true);
if (canReceive <= 0) return;
int extracted = itemEnergy.extractEnergy(canReceive, false);
ENERGY_STORAGE.receiveEnergy(maxMove, false);
setChanged();
} catch (Exception e) {
}
}
private void outputBlastingResult(int slot, int resultSlot) {
Optional<RecipeHolder<BlastingRecipe>> recipe = getFurnaceRecipe(inventory.getStackInSlot(slot));
ItemStack output = recipe.get().value().getResultItem(null);
// 2x multiplier for smelting recipes
inventory.extractItem(slot, 1, false);
inventory.setStackInSlot(resultSlot, new ItemStack(output.getItem(),
inventory.getStackInSlot(resultSlot).getCount() + (output.getCount() * 2)));
}
private void resetProgress() {
this.progress = 0;
this.maxProgress = DEFAULT_MAX_PROGRESS;
}
private void useEnergyForBlasting() {
this.ENERGY_STORAGE.extractEnergy(Blasting_ENERGY_COST, false);
}
private boolean hasEnoughEnergyToCraft(int energyCost) {
return ENERGY_STORAGE.getEnergyStored() >= energyCost;
}
private boolean canInsertItemIntoOutputSlot(ItemStack output, int slot) {
return inventory.getStackInSlot(slot).isEmpty() ||
inventory.getStackInSlot(slot).getItem() == output.getItem();
}
private boolean canInsertAmountIntoOutputSlot(int count, int slot) {
int maxCount = inventory.getStackInSlot(slot).isEmpty() ? 64 : inventory.getStackInSlot(slot).getMaxStackSize();
int currentCount = inventory.getStackInSlot(slot).getCount();
return maxCount >= currentCount + count;
}
private boolean isOutputSlotEmptyOrReceivable(int slot) {
return this.inventory.getStackInSlot(slot).isEmpty() ||
this.inventory.getStackInSlot(slot).getCount() < this.inventory.getStackInSlot(slot).getMaxStackSize();
}
private boolean hasCraftingFinished() {
return this.progress >= this.maxProgress;
}
private boolean hasFurnaceRecipe(int slot) {
Optional<RecipeHolder<BlastingRecipe>> recipe = getFurnaceRecipe(new ItemStack(inventory.getStackInSlot(slot).getItem().asItem(), 1));
if (recipe.isEmpty())
return false;
ItemStack output = recipe.get().value().getResultItem(null);
return canInsertAmountIntoOutputSlot(output.getCount() * 2, OUTPUT_SLOT) && canInsertItemIntoOutputSlot(output, OUTPUT_SLOT);
}
private Optional<RecipeHolder<BlastingRecipe>> getFurnaceRecipe(ItemStack stack) {
if (stack.isEmpty()) return Optional.empty();
return this.level.getRecipeManager()
.getRecipeFor(RecipeType.BLASTING, new SingleRecipeInput(stack), level);
}
public void sendUpdate() {
setChanged();
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
private final IItemHandler fullHandler = new SidedSlotHandler(inventory, new int[]{0,1}, true, true);
private final IItemHandler inputHandler = new SidedSlotHandler(inventory, new int[]{0,1}, true, true);
private final IItemHandler outputHandler = new SidedSlotHandler(inventory, new int[]{2,3}, false, true);
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
public IItemHandler getItemHandler(Direction direction) {
return fullHandler;
}
public IEnergyStorage getEnergyStorage(@Nullable Direction direction) {
return this.ENERGY_STORAGE;
}
private final ModEnergyStorage ENERGY_STORAGE = createEnergyStorage();
private ModEnergyStorage createEnergyStorage() {
return new ModEnergyStorage(ENERGY_CAPACITY, MAX_TRANSFER) {
@Override
public void onEnergyChanged() {
setChanged();
getLevel().sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
};
}
public ItemStackHandler getInventory() {
return inventory;
}
public void drops() {
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
for(int i = 0; i < inventory.getSlots(); i++) {
inv.setItem(i, inventory.getStackInSlot(i));
}
Containers.dropContents(this.level, this.worldPosition, inv);
}
@Override
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider pRegistries) {
tag.put("inventory", inventory.serializeNBT(pRegistries));
tag.putInt("electric_arc_furnace.progress", progress);
tag.putInt("electric_arc_furnace.maxProgress", maxProgress);
tag.putInt("electric_arc_furnace.energy", ENERGY_STORAGE.getEnergyStored());
super.saveAdditional(tag, pRegistries);
}
@Override
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider pRegistries) {
super.loadAdditional(tag, pRegistries);
inventory.deserializeNBT(pRegistries, tag.getCompound("inventory"));
progress = tag.getInt("electric_arc_furnace.progress");
maxProgress = tag.getInt("electric_arc_furnace.maxProgress");
ENERGY_STORAGE.setEnergy(tag.getInt("electric_arc_furnace.energy"));
}
@Override
public Component getDisplayName() {
return null;
}
@Override
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
}
@Nullable
@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}
@Override
public CompoundTag getUpdateTag(HolderLookup.Provider pRegistries) {
return saveWithoutMetadata(pRegistries);
}
}

View File

@@ -0,0 +1,100 @@
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.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.*;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import net.xevianlight.aphelion.screen.TestBlockMenu;
import net.xevianlight.aphelion.util.SidedSlotHandler;
import org.jetbrains.annotations.Nullable;
public class TestBlockEntity extends BlockEntity implements MenuProvider {
private final int SIZE = 1;
private NonNullList<ItemStack> items = NonNullList.withSize(SIZE, ItemStack.EMPTY);
public TestBlockEntity(BlockPos pos, BlockState blockState) {
super(ModBlockEntities.TEST_BLOCK_ENTITY.get(), pos, blockState);
}
public final ItemStackHandler inventory = new ItemStackHandler(SIZE) {
@Override
protected void onContentsChanged(int slot) {
setChanged();
if(!level.isClientSide()) {
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
}
};
public void tick(Level level, BlockPos pos, BlockState blockState) {
inventory.insertItem(0, new ItemStack(Items.DIAMOND), false);
}
public void sendUpdate() {
setChanged();
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
private final IItemHandler topHandler = new SidedSlotHandler(inventory, new int[]{0}, true, false);
private final IItemHandler bottomHandler = new SidedSlotHandler(inventory, new int[]{0}, false, true);
private final IItemHandler jadeHandler = new SidedSlotHandler(inventory, new int[]{0}, false, false);
public IItemHandler getItemHandler(Direction direction) {
if (direction == Direction.UP) return topHandler;
if (direction == Direction.DOWN) return bottomHandler;
if (direction == null) return jadeHandler;
return null;
}
public ItemStackHandler getInventory() {
return inventory;
}
public void drops() {
SimpleContainer inv = new SimpleContainer(inventory.getSlots());
for(int i = 0; i < inventory.getSlots(); i++) {
inv.setItem(i, inventory.getStackInSlot(i));
}
Containers.dropContents(this.level, this.worldPosition, inv);
}
@Override
protected void saveAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
pTag.put("inventory", inventory.serializeNBT(pRegistries));
super.saveAdditional(pTag, pRegistries);
}
@Override
protected void loadAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
super.loadAdditional(pTag, pRegistries);
inventory.deserializeNBT(pRegistries, pTag.getCompound("inventory"));
}
@Override
public Component getDisplayName() {
return null;
}
@Override
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
return new TestBlockMenu(i, inventory, this);
}
}

View File

@@ -0,0 +1,93 @@
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.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.*;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
import org.jetbrains.annotations.Nullable;
public class TestBlockEntity2 extends BaseContainerBlockEntity implements WorldlyContainer {
// The constructor, like before.
public TestBlockEntity2 (BlockPos pos, BlockState blockState) {
super(ModBlockEntities.TEST_BLOCK_ENTITY.get(), pos, blockState);
}
// The container size. This can of course be any value you want.
public static final int SIZE = 9;
// Our item stack list. This is not final due to #setItems existing.
private NonNullList<ItemStack> items = NonNullList.withSize(SIZE, ItemStack.EMPTY);
// The container size, like before.
@Override
public int getContainerSize() {
return SIZE;
}
// The getter for our item stack list.
@Override
protected NonNullList<ItemStack> getItems() {
return items;
}
// The setter for our item stack list.
@Override
protected void setItems(NonNullList<ItemStack> items) {
this.items = items;
}
// The display name of the menu. Don't forget to add a translation!
@Override
protected Component getDefaultName() {
return Component.translatable("container.examplemod.myblockentity");
}
// The menu to create from this container. See below for what to return here.
@Override
protected AbstractContainerMenu createMenu(int containerId, Inventory inventory) {
return null;
}
@Override
public int[] getSlotsForFace(Direction direction) {
return new int[] {0,1,2,3,4,5,6,7,8};
}
@Override
public boolean canPlaceItemThroughFace(int i, ItemStack itemStack, @Nullable Direction direction) {
return true;
}
@Override
public boolean canTakeItemThroughFace(int i, ItemStack itemStack, Direction direction) {
return true;
}
@Override
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider provider) {
super.loadAdditional(nbt, provider);
this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY);
ContainerHelper.loadAllItems(nbt, this.items, provider);
}
@Override
protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider provider) {
super.saveAdditional(nbt, provider);
ContainerHelper.saveAllItems(nbt, this.items, provider);
}
public void dropContents() {
for (int i = 0; i < items.size(); i++) {
ItemStack stack = getItem(i);
Containers.dropItemStack(level, (double) worldPosition.getX(), (double) worldPosition.getY(), (double) worldPosition.getZ(), stack);
}
}
}

View File

@@ -0,0 +1,37 @@
package net.xevianlight.aphelion.block.entity.energy;
import net.neoforged.neoforge.energy.EnergyStorage;
public abstract class ModEnergyStorage extends EnergyStorage {
public ModEnergyStorage(int capacity, int maxTransfer) {
super(capacity, maxTransfer);
}
@Override
public int extractEnergy(int maxExtract, boolean simulate) {
int extractedEnergy = super.extractEnergy(maxExtract, simulate);
if(extractedEnergy != 0) {
onEnergyChanged();
}
return extractedEnergy;
}
@Override
public int receiveEnergy(int maxReceive, boolean simulate) {
int receiveEnergy = super.receiveEnergy(maxReceive, simulate);
if(receiveEnergy != 0) {
onEnergyChanged();
}
return receiveEnergy;
}
public int setEnergy(int energy) {
this.energy = energy;
return energy;
}
public abstract void onEnergyChanged();
}

View File

@@ -0,0 +1,43 @@
package net.xevianlight.aphelion.block.entity.energy;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.energy.IEnergyStorage;
public class ModEnergyUtil {
public static boolean move(BlockPos from, BlockPos to, int amount, Level level) {
IEnergyStorage fromStorage = level.getCapability(Capabilities.EnergyStorage.BLOCK, from, null);
IEnergyStorage toStorage = level.getCapability(Capabilities.EnergyStorage.BLOCK, to, null);
if(canEnergyStorageExtractThisAmount(fromStorage, amount)) {
return false;
}
if(canEnergyStorageStillReceiveEnergy(toStorage)) {
return false;
}
int maxAmountToReceive = toStorage.receiveEnergy(amount, true);
int extractedEnergy = fromStorage.extractEnergy(maxAmountToReceive, false);
toStorage.receiveEnergy(extractedEnergy, false);
return true;
}
private static boolean canEnergyStorageStillReceiveEnergy(IEnergyStorage toStorage) {
// No more Energy to draw or cannot extract
return toStorage.getEnergyStored() >= toStorage.getMaxEnergyStored() || !toStorage.canReceive();
}
private static boolean canEnergyStorageExtractThisAmount(IEnergyStorage fromStorage, int amount) {
// No more Space to receive or cannot receive
return fromStorage.getEnergyStored() <= 0 || fromStorage.getEnergyStored() < amount || !fromStorage.canExtract();
}
public static boolean doesBlockHaveEnergyStorage(BlockPos positionToCheck, Level level) {
return level.getBlockEntity(positionToCheck) != null
&& level.getCapability(Capabilities.EnergyStorage.BLOCK, positionToCheck, null) != null;
}
}

View File

@@ -0,0 +1,57 @@
package net.xevianlight.aphelion.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.DimensionSpecialEffects;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent;
import net.neoforged.neoforge.client.event.RegisterDimensionSpecialEffectsEvent;
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.client.dimension.AphelionDimensionRenderers;
import java.util.function.BiConsumer;
// This class will not load on dedicated servers. Accessing client side code from here is safe.
@Mod(value = Aphelion.MOD_ID, dist = Dist.CLIENT)
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
public class AphelionClient {
public AphelionClient(ModContainer container) {
// Allows NeoForge to create a config screen for this mod's configs.
// The config screen is accessed by going to the Mods screen > clicking on your mod > clicking on config.
// Do not forget to add translations for your config options to the en_us.json file.
container.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
}
@SubscribeEvent
static void onClientSetup(FMLClientSetupEvent event) {
// Some client setup code
Aphelion.LOGGER.info("HELLO FROM CLIENT SETUP");
Aphelion.LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName());
}
@SubscribeEvent
public static void onClientReloadListeners(RegisterClientReloadListenersEvent event) {
onAddReloadListener((id, listener) -> event.registerReloadListener(listener));
}
public static void onAddReloadListener(BiConsumer<ResourceLocation, PreparableReloadListener> consumer) {
consumer.accept(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "planet_renderers"), new AphelionDimensionRenderers());
}
@SubscribeEvent
public static void onRegisterDimensionEffects(RegisterDimensionSpecialEffectsEvent event) {
event.register(
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"),
new net.xevianlight.aphelion.client.dimension.SpaceSkyEffects()
);
}
}

View File

@@ -1,4 +1,4 @@
package net.xevianlight.extreme_rocketry;
package net.xevianlight.aphelion.client;
import java.util.List;
@@ -8,7 +8,7 @@ import net.neoforged.neoforge.common.ModConfigSpec;
// An example config class. This is not required, but it's a good idea to have one to keep your config organized.
// Demonstrates how to use Neo's config APIs
public class Config {
public class AphelionConfig {
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
public static final ModConfigSpec.BooleanValue LOG_DIRT_BLOCK = BUILDER
@@ -26,9 +26,9 @@ public class Config {
// a list of strings that are treated as resource locations for items
public static final ModConfigSpec.ConfigValue<List<? extends String>> ITEM_STRINGS = BUILDER
.comment("A list of items to log on common setup.")
.defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), () -> "", Config::validateItemName);
.defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), () -> "", AphelionConfig::validateItemName);
static final ModConfigSpec SPEC = BUILDER.build();
public static final ModConfigSpec SPEC = BUILDER.build();
private static boolean validateItemName(final Object obj) {
return obj instanceof String itemName && BuiltInRegistries.ITEM.containsKey(ResourceLocation.parse(itemName));

View File

@@ -0,0 +1,44 @@
package net.xevianlight.aphelion.client;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.client.dimension.DimensionRenderer;
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
import net.xevianlight.aphelion.client.dimension.SpaceSkyEffects;
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
public class AphelionDebugOverlay {
@SubscribeEvent
public static void onDebugText(CustomizeGuiOverlayEvent.DebugText event) {
Minecraft mc = Minecraft.getInstance();
if (mc.level == null || mc.player == null) return;
// Only show in your space dimension (optional)
if (!mc.level.dimension().location().equals(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"))) {
return;
}
var camPos = mc.gameRenderer.getMainCamera().getPosition();
ResourceLocation orbitId = SpaceSkyEffects.orbitForPos(camPos);
DimensionRenderer r = DimensionRendererCache.getOrDefault(orbitId);
String rendererSummary = (r == null)
? "<missing>"
: ("customSky=" + r.customSky()
+ ", thickFog=" + r.hasThickFog()
+ ", fog=" + r.hasFog());
// Left side of F3
event.getLeft().add("");
event.getLeft().add("Aphelion:");
event.getLeft().add(" Orbit: " + orbitId);
event.getLeft().add(" Sky: " + rendererSummary);
}
}

View File

@@ -0,0 +1,42 @@
package net.xevianlight.aphelion.client.dimension;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.Level;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.util.Constants;
import java.util.HashMap;
import java.util.Map;
public class AphelionDimensionRenderers extends SimpleJsonResourceReloadListener {
public AphelionDimensionRenderers() {
super(Constants.GSON, "dimension_renderers");
}
@Override
protected void apply(Map<ResourceLocation, JsonElement> object,
ResourceManager resourceManager,
ProfilerFiller profiler) {
Map<ResourceLocation, DimensionRenderer> renderers = new HashMap<>();
object.forEach((key, value) -> {
JsonObject json = GsonHelper.convertToJsonObject(value, "dimension_renderer");
DimensionRenderer renderer = DimensionRenderer.CODEC.parse(JsonOps.INSTANCE, json).getOrThrow();
// IMPORTANT: use the *resource id* of the json as the lookup key
// so "effects": "aphelion:space" maps to space.json automatically.
renderers.put(key, renderer);
});
DimensionRendererCache.registerPlanetRenderers(renderers);
}
}

View File

@@ -0,0 +1,39 @@
package net.xevianlight.aphelion.client.dimension;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import java.util.Optional;
public record DimensionRenderer(
ResourceKey<Level> dimension,
boolean customClouds,
boolean customSky,
boolean customWeather,
boolean hasThickFog,
boolean hasFog,
int sunriseColor,
int sunriseAngle,
boolean renderInRain,
boolean renderVoidFog,
double horizonHeight,
float clearColorScale
) {
public static final Codec<DimensionRenderer> CODEC = RecordCodecBuilder.create(inst -> inst.group(
ResourceKey.codec(Registries.DIMENSION).fieldOf("dimension").forGetter(DimensionRenderer::dimension),
Codec.BOOL.fieldOf("custom_clouds").forGetter(DimensionRenderer::customClouds),
Codec.BOOL.fieldOf("custom_sky").forGetter(DimensionRenderer::customSky),
Codec.BOOL.fieldOf("custom_weather").forGetter(DimensionRenderer::customWeather),
Codec.BOOL.fieldOf("has_thick_fog").forGetter(DimensionRenderer::hasThickFog),
Codec.BOOL.fieldOf("has_fog").forGetter(DimensionRenderer::hasFog),
Codec.INT.fieldOf("sunrise_color").forGetter(DimensionRenderer::sunriseColor),
Codec.INT.fieldOf("sunrise_angle").forGetter(DimensionRenderer::sunriseAngle),
Codec.BOOL.fieldOf("render_in_rain").forGetter(DimensionRenderer::renderInRain),
Codec.BOOL.fieldOf("render_void_fog").forGetter(DimensionRenderer::renderVoidFog),
Codec.DOUBLE.fieldOf("horizon_height").forGetter(DimensionRenderer::horizonHeight),
Codec.FLOAT.fieldOf("clear_color_scale").forGetter(DimensionRenderer::clearColorScale)
).apply(inst, DimensionRenderer::new));
}

View File

@@ -0,0 +1,23 @@
package net.xevianlight.aphelion.client.dimension;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.Level;
import java.util.HashMap;
import java.util.Map;
public final class DimensionRendererCache {
public static final Map<ResourceLocation, DimensionRenderer> RENDERERS = new HashMap<>();
public static void registerPlanetRenderers(Map<ResourceLocation, DimensionRenderer> renderers) {
RENDERERS.clear();
RENDERERS.putAll(renderers);
}
public static DimensionRenderer getOrDefault(ResourceLocation id) {
return RENDERERS.getOrDefault(id, null);
}
}

View File

@@ -0,0 +1,60 @@
package net.xevianlight.aphelion.client.dimension;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.DimensionSpecialEffects;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.xevianlight.aphelion.Aphelion;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
public class DimensionSkyEffects extends DimensionSpecialEffects {
private final ResourceLocation effectsId;
boolean customSky;
public DimensionSkyEffects(ResourceLocation effectsId) {
super(192, false, SkyType.NORMAL, false, false);
this.effectsId = effectsId;
}
private DimensionRenderer renderer() {
return DimensionRendererCache.getOrDefault(effectsId);
}
// @Override
// public boolean renderVoidFog() {
// return true;
// }
@Override
public boolean renderSky(ClientLevel level, int ticks, float partialTick, Matrix4f modelViewMatrix, Camera camera, Matrix4f projectionMatrix, boolean isFoggy, Runnable setupFog) {
return super.renderSky(level, ticks, partialTick, modelViewMatrix, camera, projectionMatrix, isFoggy, setupFog);
}
@Override
public Vec3 getBrightnessDependentFogColor(Vec3 fogColor, float brightness) {
if (renderer().hasFog()) {
return fogColor.multiply(
brightness * 0.94 + 0.06,
brightness * 0.94 + 0.06,
brightness * 0.91 + 0.09);
}
return Vec3.ZERO;
}
@Override
public boolean isFoggyAt(int x, int z) {
return renderer().hasThickFog();
}
@Override
public @Nullable float[] getSunriseColor(float timeOfDay, float partialTicks) {
return new float[]{0,0,0,0};
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.client.dimension;
public class DimensionSkyRenderer {
DimensionRenderer renderer;
DimensionSkyRenderer(DimensionRenderer renderer) { this.renderer = renderer; }
}

View File

@@ -0,0 +1,12 @@
package net.xevianlight.aphelion.client.dimension;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
public record OrbitSkyDefinition(
ResourceLocation id,
Vec3 skyColor
) {
}

View File

@@ -0,0 +1,61 @@
package net.xevianlight.aphelion.client.dimension;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.DimensionSpecialEffects;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.xevianlight.aphelion.Aphelion;
import org.joml.Matrix4f;
public class SpaceSkyEffects extends DimensionSpecialEffects {
public SpaceSkyEffects() {
super(192, false, SkyType.NORMAL, false, false);
}
@Override
public boolean renderSky(ClientLevel level, int ticks, float partialTick, Matrix4f modelViewMatrix, Camera camera, Matrix4f projectionMatrix, boolean isFoggy, Runnable setupFog) {
ResourceLocation id = orbitForPos(net.minecraft.client.Minecraft.getInstance()
.gameRenderer.getMainCamera().getPosition());
// Aphelion.LOGGER.info("Loaded dimension_renderers: {}", DimensionRendererCache.getOrDefault(id).toString());
// Return true, meaning we are rendering the sky ourselves. Vanilla will not draw its sky.
if (DimensionRendererCache.getOrDefault(id).customSky())
return true;
return super.renderSky(level, ticks, partialTick, modelViewMatrix, camera, projectionMatrix, isFoggy, setupFog);
}
@Override
public Vec3 getBrightnessDependentFogColor(Vec3 fogColor, float brightness) {
ResourceLocation id = orbitForPos(net.minecraft.client.Minecraft.getInstance()
.gameRenderer.getMainCamera().getPosition());
if (DimensionRendererCache.getOrDefault(id).hasFog()) {
return fogColor.multiply(
brightness * 0.94 + 0.06,
brightness * 0.94 + 0.06,
brightness * 0.91 + 0.09);
}
return Vec3.ZERO;
}
@Override
public boolean isFoggyAt(int i, int i1) {
ResourceLocation id = orbitForPos(net.minecraft.client.Minecraft.getInstance()
.gameRenderer.getMainCamera().getPosition());
return DimensionRendererCache.getOrDefault(id).hasThickFog();
}
public static ResourceLocation orbitForPos(Vec3 pos) {
double r = Math.sqrt(pos.x * pos.x + pos.z * pos.z);
if (r < 100) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/earth");
if (r < 200) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/mars");
if (r < 300) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/venus");
return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/default");
}
}

View File

@@ -0,0 +1,30 @@
package net.xevianlight.aphelion.core.init;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.entity.custom.DimensionChangerBlockEntity;
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
import java.util.function.Supplier;
public class ModBlockEntities {
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, Aphelion.MOD_ID);
public static final Supplier<BlockEntityType<TestBlockEntity>> TEST_BLOCK_ENTITY =
BLOCK_ENTITIES.register("test_block_entity", () -> BlockEntityType.Builder.of(
TestBlockEntity::new, ModBlocks.TEST_BLOCK.get()).build(null)
);
public static final Supplier<BlockEntityType<DimensionChangerBlockEntity>> DIMENSION_CHANGER_BLOCK_ENTITY =
BLOCK_ENTITIES.register("dimension_changer_block_entity", () -> BlockEntityType.Builder.of(
DimensionChangerBlockEntity::new, ModBlocks.DIMENSION_CHANGER.get()).build(null)
);
public static final Supplier<BlockEntityType<ElectricArcFurnaceEntity>> ELECTRIC_ARC_FURNACE_ENTITY =
BLOCK_ENTITIES.register("electric_arc_furnace_block_entity", () -> BlockEntityType.Builder.of(
ElectricArcFurnaceEntity::new, ModBlocks.ELECTRIC_ARC_FURNACE.get()).build(null)
);
}

View File

@@ -0,0 +1,19 @@
package net.xevianlight.aphelion.core.init;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.custom.BlockSteel;
import net.xevianlight.aphelion.block.custom.DimensionChangerBlock;
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
import net.xevianlight.aphelion.block.custom.TestBlock;
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> 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()));
}

View File

@@ -0,0 +1,43 @@
package net.xevianlight.aphelion.core.init;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.fluid.ModFluids;
import java.util.function.Supplier;
public class ModCreativeTabs {
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TAB = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Aphelion.MOD_ID);
public static final Supplier<CreativeModeTab> APHELION_ITEMS_TAB = CREATIVE_MODE_TAB.register("aphelion_items_tab",
() -> CreativeModeTab.builder().icon(() -> new ItemStack(ModItems.TEST_ITEM.get()))
.title(Component.translatable("creativetab.aphelion.aphelion_items"))
.displayItems((itemDisplayParameters, output) -> {
output.accept(ModItems.TEST_ITEM);
output.accept(ModItems.INGOT_ALUMINUM);
output.accept(ModItems.INGOT_STEEL);
output.accept(ModItems.INGOT_TITANIUM);
output.accept(ModItems.INGOT_URANIUM);
output.accept(ModItems.INGOT_COBALT);
output.accept(ModItems.INGOT_TUNGSTEN);
output.accept(ModItems.INGOT_NEODYMIUM);
output.accept(ModItems.INGOT_IRIDIUM);
output.accept(ModFluids.OIL_BUCKET);
output.accept(ModItems.MUSIC_DISC_BIT_SHIFT);
}).build());
public static final Supplier<CreativeModeTab> APHELION_BLOCKS_TAB = CREATIVE_MODE_TAB.register("aphelion_blocks_tab",
() -> CreativeModeTab.builder().icon(() -> new ItemStack(ModItems.TEST_BLOCK.get()))
.withTabsBefore(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "aphelion_items_tab"))
.title(Component.translatable("creativetab.aphelion.aphelion_blocks"))
.displayItems((itemDisplayParameters, output) -> {
output.accept(ModItems.TEST_BLOCK);
output.accept(ModItems.ELECTRIC_ARC_FURNACE);
output.accept(ModItems.BLOCK_STEEL);
}).build());
}

View File

@@ -0,0 +1,38 @@
package net.xevianlight.aphelion.core.init;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Rarity;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.custom.BlockSteel;
import net.xevianlight.aphelion.block.custom.DimensionChangerBlock;
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
import net.xevianlight.aphelion.block.custom.TestBlock;
import net.xevianlight.aphelion.item.*;
public class ModItems {
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(Aphelion.MOD_ID);
public static final DeferredItem<Item> TEST_ITEM = ITEMS.register("test_item", TestItem::new);
public static final DeferredItem<Item> INGOT_ALUMINUM = ITEMS.register("ingot_aluminum", IngotAluminum::new);
public static final DeferredItem<Item> INGOT_STEEL = ITEMS.register("ingot_steel", IngotSteel::new);
public static final DeferredItem<Item> INGOT_TITANIUM = ITEMS.register("ingot_titanium", IngotTitanium::new);
public static final DeferredItem<Item> INGOT_URANIUM = ITEMS.register("ingot_uranium", IngotUranium::new);
public static final DeferredItem<Item> INGOT_COBALT = ITEMS.register("ingot_cobalt", IngotCobalt::new);
public static final DeferredItem<Item> INGOT_TUNGSTEN = ITEMS.register("ingot_tungsten", IngotTungsten::new);
public static final DeferredItem<Item> INGOT_NEODYMIUM = ITEMS.register("ingot_neodymium", IngotNeodymium::new);
public static final DeferredItem<Item> INGOT_IRIDIUM = ITEMS.register("ingot_iridium", IngotIridium::new);
public static final DeferredItem<Item> MUSIC_DISC_BIT_SHIFT = ITEMS.register("music_disc_bit_shift",
() -> new Item(new Item.Properties().jukeboxPlayable(ModSounds.BIT_SHIFT_KEY).stacksTo(1).rarity(Rarity.RARE)));
// Block Items
public static final DeferredItem<BlockItem> TEST_BLOCK = ITEMS.register("test_block", () -> new BlockItem(ModBlocks.TEST_BLOCK.get(), TestBlock.getItemProperties().stacksTo(9999)));
public static final DeferredItem<BlockItem> DIMENSION_CHANGER = ITEMS.register("dimension_changer", () -> new BlockItem(ModBlocks.DIMENSION_CHANGER.get(), DimensionChangerBlock.getItemProperties()));
public static final DeferredItem<BlockItem> ELECTRIC_ARC_FURNACE = ITEMS.register("electric_arc_furnace", () -> new BlockItem(ModBlocks.ELECTRIC_ARC_FURNACE.get(), ElectricArcFurnace.getItemProperties()));
public static final DeferredItem<BlockItem> BLOCK_STEEL = ITEMS.register("block_steel", () -> new BlockItem(ModBlocks.BLOCK_STEEL.get(), BlockSteel.getItemProperties()));
}

View File

@@ -0,0 +1,34 @@
package net.xevianlight.aphelion.core.init;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.JukeboxSong;
import net.neoforged.bus.api.IEventBus;
import net.xevianlight.aphelion.Aphelion;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
public class ModSounds {
public static final DeferredRegister<SoundEvent> SOUND_EVENTS =
DeferredRegister.create(Registries.SOUND_EVENT, Aphelion.MOD_ID);
private static ResourceKey<JukeboxSong> createSong(String name) {
return ResourceKey.create(Registries.JUKEBOX_SONG, ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name));
}
public static final Supplier<SoundEvent> BIT_SHIFT = registerSoundEvent("bit_shift");
public static final ResourceKey<JukeboxSong> BIT_SHIFT_KEY = createSong("bit_shift");
private static Supplier<SoundEvent> registerSoundEvent(String name) {
ResourceLocation id = ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name);
return SOUND_EVENTS.register(name, () -> SoundEvent.createVariableRangeEvent(id));
}
public static void register(IEventBus eventBus) {
SOUND_EVENTS.register(eventBus);
}
}

View File

@@ -0,0 +1,42 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.PackOutput;
import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.common.data.BlockTagsProvider;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.data.event.GatherDataEvent;
import net.xevianlight.aphelion.Aphelion;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@EventBusSubscriber(modid = Aphelion.MOD_ID)
public class DataGenerators {
@SubscribeEvent
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
PackOutput packOutput = generator.getPackOutput();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
CompletableFuture<HolderLookup.Provider> lookupProvider =event.getLookupProvider();
generator.addProvider(event.includeServer(), new LootTableProvider(packOutput, Collections.emptySet(),
List.of(new LootTableProvider.SubProviderEntry(ModBlockLootTableProvider::new, LootContextParamSets.BLOCK)), lookupProvider));
generator.addProvider(event.includeClient(), new ModItemModelProvider(packOutput, existingFileHelper));
generator.addProvider(event.includeClient(), new ModBlockStateProvider(packOutput, existingFileHelper));
BlockTagsProvider blockTagsProvider = new ModBlockTagProvider(packOutput, lookupProvider, existingFileHelper);
generator.addProvider(event.includeServer(), blockTagsProvider);
generator.addProvider(event.includeServer(), new ModItemTagProvider(packOutput, lookupProvider, blockTagsProvider.contentsGetter(), existingFileHelper));
generator.addProvider(event.includeServer(), new ModFluidTagsProvider(packOutput, lookupProvider, existingFileHelper));
generator.addProvider(event.includeServer(), new ModRecipeProvider(packOutput, lookupProvider));
generator.addProvider(event.includeServer(), new ModDataMapProvider(packOutput, lookupProvider));
}
}

View File

@@ -0,0 +1,29 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.loot.BlockLootSubProvider;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.level.block.Block;
import net.xevianlight.aphelion.core.init.ModBlocks;
import java.util.Set;
public class ModBlockLootTableProvider extends BlockLootSubProvider {
protected ModBlockLootTableProvider(HolderLookup.Provider registries) {
super(Set.of(), FeatureFlags.REGISTRY.allFlags(), registries);
}
@Override
protected void generate() {
dropSelf(ModBlocks.TEST_BLOCK.get());
dropSelf(ModBlocks.BLOCK_STEEL.get());
dropSelf(ModBlocks.DIMENSION_CHANGER.get());
dropSelf(ModBlocks.ELECTRIC_ARC_FURNACE.get());
}
@Override
protected Iterable<Block> getKnownBlocks() {
return ModBlocks.BLOCKS.getEntries().stream().map(Holder::value)::iterator;
}
}

View File

@@ -0,0 +1,38 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.data.PackOutput;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.client.model.generators.BlockStateProvider;
import net.neoforged.neoforge.client.model.generators.ModelFile;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModBlocks;
public class ModBlockStateProvider extends BlockStateProvider {
public ModBlockStateProvider(PackOutput output, ExistingFileHelper exFileHelper) {
super(output, Aphelion.MOD_ID, exFileHelper);
}
@Override
protected void registerStatesAndModels() {
blockWithItem(ModBlocks.TEST_BLOCK);
horizontalBlock(ModBlocks.ELECTRIC_ARC_FURNACE.get(), models().orientable("aphelion:electric_arc_furnace",
mcLoc("block/blast_furnace_side"),
modLoc("block/electric_arc_furnace_front"),
mcLoc("block/blast_furnace_top")));
blockItem(ModBlocks.ELECTRIC_ARC_FURNACE);
blockWithItem(ModBlocks.BLOCK_STEEL);
blockWithItem(ModBlocks.DIMENSION_CHANGER);
}
private void blockWithItem(DeferredBlock<?> deferredBlock) {
simpleBlockWithItem(deferredBlock.get(), cubeAll(deferredBlock.get()));
}
private void blockItem(DeferredBlock<Block> deferredBlock) {
simpleBlockItem(deferredBlock.get(), new ModelFile.UncheckedModelFile("aphelion:block/" + deferredBlock.getId().getPath()));
}
}

View File

@@ -0,0 +1,37 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.tags.BlockTags;
import net.neoforged.neoforge.common.data.BlockTagsProvider;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModBlocks;
import net.xevianlight.aphelion.util.ModTags;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class ModBlockTagProvider extends BlockTagsProvider {
public ModBlockTagProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, @Nullable ExistingFileHelper existingFileHelper) {
super(output, lookupProvider, Aphelion.MOD_ID, existingFileHelper);
}
@Override
protected void addTags(HolderLookup.Provider provider) {
tag(BlockTags.MINEABLE_WITH_PICKAXE)
.add(ModBlocks.TEST_BLOCK.get())
.add(ModBlocks.ELECTRIC_ARC_FURNACE.get())
.add(ModBlocks.BLOCK_STEEL.get());
tag(BlockTags.NEEDS_STONE_TOOL)
.add(ModBlocks.TEST_BLOCK.get())
.add(ModBlocks.ELECTRIC_ARC_FURNACE.get())
.add(ModBlocks.BLOCK_STEEL.get());
tag(ModTags.Blocks.STORAGE_BLOCKS_STEEL)
.add(ModBlocks.BLOCK_STEEL.get());
tag(ModTags.Blocks.STORAGE_BLOCKS)
.add(ModBlocks.BLOCK_STEEL.get());
}
}

View File

@@ -0,0 +1,22 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.neoforged.neoforge.common.data.DataMapProvider;
import net.neoforged.neoforge.registries.datamaps.builtin.FurnaceFuel;
import net.neoforged.neoforge.registries.datamaps.builtin.NeoForgeDataMaps;
import net.xevianlight.aphelion.core.init.ModItems;
import java.util.concurrent.CompletableFuture;
public class ModDataMapProvider extends DataMapProvider {
protected ModDataMapProvider(PackOutput packOutput, CompletableFuture<HolderLookup.Provider> lookupProvider) {
super(packOutput, lookupProvider);
}
@Override
protected void gather(HolderLookup.Provider provider) {
this.builder(NeoForgeDataMaps.FURNACE_FUELS)
.add(ModItems.TEST_ITEM.getId(), new FurnaceFuel(1200), false);
}
}

View File

@@ -0,0 +1,26 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
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.fluid.ModFluids;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class ModFluidTagsProvider extends FluidTagsProvider {
public ModFluidTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> provider, @Nullable ExistingFileHelper existingFileHelper) {
super(output, provider, Aphelion.MOD_ID, existingFileHelper);
}
@Override
protected void addTags(HolderLookup.Provider provider) {
// tag(FluidTags.LAVA)
// .add(ModFluids.SOURCE_OIL_FLUID.get())
// .add(ModFluids.FLOWING_OIL_FLUID.get());
}
}

View File

@@ -0,0 +1,30 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.data.PackOutput;
import net.neoforged.neoforge.client.model.generators.ItemModelProvider;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModItems;
import net.xevianlight.aphelion.fluid.ModFluids;
public class ModItemModelProvider extends ItemModelProvider {
public ModItemModelProvider(PackOutput output, ExistingFileHelper existingFileHelper) {
super(output, Aphelion.MOD_ID, existingFileHelper);
}
@Override
protected void registerModels() {
basicItem(ModItems.TEST_ITEM.get());
basicItem(ModItems.INGOT_ALUMINUM.get());
basicItem(ModItems.INGOT_STEEL.get());
basicItem(ModItems.INGOT_TITANIUM.get());
basicItem(ModItems.INGOT_URANIUM.get());
basicItem(ModItems.INGOT_COBALT.get());
basicItem(ModItems.INGOT_TUNGSTEN.get());
basicItem(ModItems.INGOT_NEODYMIUM.get());
basicItem(ModItems.INGOT_IRIDIUM.get());
basicItem(ModFluids.OIL_BUCKET.get());
basicItem(ModItems.MUSIC_DISC_BIT_SHIFT.get());
}
}

View File

@@ -0,0 +1,66 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.data.tags.ItemTagsProvider;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModItems;
import net.xevianlight.aphelion.util.ModTags;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class ModItemTagProvider extends ItemTagsProvider {
public ModItemTagProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, CompletableFuture<TagLookup<Block>> blockTags, @Nullable ExistingFileHelper existingFileHelper) {
super(output, lookupProvider, blockTags, Aphelion.MOD_ID, existingFileHelper);
}
@Override
protected void addTags(HolderLookup.Provider provider) {
tag(ModTags.Items.TEST_TAG)
.add(ModItems.TEST_ITEM.get());
tag(ModTags.Items.INGOTS)
.add(ModItems.INGOT_ALUMINUM.get())
.add(ModItems.INGOT_STEEL.get())
.add(ModItems.INGOT_TITANIUM.get())
.add(ModItems.INGOT_URANIUM.get())
.add(ModItems.INGOT_COBALT.get())
.add(ModItems.INGOT_TUNGSTEN.get())
.add(ModItems.INGOT_NEODYMIUM.get())
.add(ModItems.INGOT_IRIDIUM.get());
tag(ModTags.Items.INGOT_ALUMINUM)
.add(ModItems.INGOT_ALUMINUM.get());
tag(ModTags.Items.INGOT_STEEL)
.add(ModItems.INGOT_STEEL.get());
tag(ModTags.Items.INGOT_TITANIUM)
.add(ModItems.INGOT_TITANIUM.get());
tag(ModTags.Items.INGOT_URANIUM)
.add(ModItems.INGOT_URANIUM.get());
tag(ModTags.Items.INGOT_COBALT)
.add(ModItems.INGOT_COBALT.get());
tag(ModTags.Items.INGOT_TUNGSTEN)
.add(ModItems.INGOT_TUNGSTEN.get());
tag(ModTags.Items.INGOT_NEODYMIUM)
.add(ModItems.INGOT_NEODYMIUM.get());
tag(ModTags.Items.INGOT_IRIDIUM)
.add(ModItems.INGOT_IRIDIUM.get());
tag(ModTags.Items.STORAGE_BLOCKS)
.add(ModItems.BLOCK_STEEL.get());
tag(ModTags.Items.STORAGE_BLOCKS_STEEL)
.add(ModItems.BLOCK_STEEL.get());
}
}

View File

@@ -0,0 +1,80 @@
package net.xevianlight.aphelion.datagen;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.data.recipes.*;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.ItemLike;
import net.neoforged.neoforge.common.conditions.IConditionBuilder;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModBlocks;
import net.xevianlight.aphelion.core.init.ModItems;
import net.xevianlight.aphelion.util.ModTags;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class ModRecipeProvider extends RecipeProvider implements IConditionBuilder {
public ModRecipeProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
super(output, registries);
}
@Override
protected void buildRecipes(RecipeOutput recipeOutput) {
List<ItemLike> TEST_SMELTABLES = List.of(ModItems.TEST_ITEM, ModBlocks.TEST_BLOCK);
//TEST BLOCK
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.TEST_BLOCK.get())
.pattern("TTT")
.pattern("TTT")
.pattern("TTT")
.define('T', ModItems.TEST_ITEM.get())
.unlockedBy("has_test_item", has(ModItems.TEST_ITEM)).save(recipeOutput, "aphelion:test_shaped_recipe");
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.TEST_ITEM.get(), 9)
.requires(ModBlocks.TEST_BLOCK)
.unlockedBy("has_test_block", has(ModBlocks.TEST_BLOCK)).save(recipeOutput, "aphelion:test_shapeless_recipe");
//STEEL BLOCK
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.BLOCK_STEEL.get())
.pattern("III")
.pattern("III")
.pattern("III")
.define('I', ModTags.Items.INGOT_STEEL)
.unlockedBy("has_steel_ingot", has(ModItems.INGOT_ALUMINUM)).save(recipeOutput, "aphelion:steel_to_block");
ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItems.INGOT_STEEL.get(), 9)
.requires(ModBlocks.BLOCK_STEEL)
.unlockedBy("has_steel_block", has(ModBlocks.BLOCK_STEEL)).save(recipeOutput, "aphelion:steel_to_ingot");
oreSmelting(recipeOutput, TEST_SMELTABLES, RecipeCategory.MISC, Items.IRON_INGOT, 0.25f, 200, "test");
}
protected static void oreSmelting(RecipeOutput recipeOutput, List<ItemLike> pIngredients, RecipeCategory pCategory, ItemLike pResult,
float pExperience, int pCookingTIme, String pGroup) {
oreCooking(recipeOutput, RecipeSerializer.SMELTING_RECIPE, SmeltingRecipe::new, pIngredients, pCategory, pResult,
pExperience, pCookingTIme, pGroup, "_from_smelting");
}
protected static void oreBlasting(RecipeOutput recipeOutput, List<ItemLike> pIngredients, RecipeCategory pCategory, ItemLike pResult,
float pExperience, int pCookingTime, String pGroup) {
oreCooking(recipeOutput, RecipeSerializer.BLASTING_RECIPE, BlastingRecipe::new, pIngredients, pCategory, pResult,
pExperience, pCookingTime, pGroup, "_from_blasting");
}
protected static <T extends AbstractCookingRecipe> void oreCooking(RecipeOutput recipeOutput, RecipeSerializer<T> pCookingSerializer, AbstractCookingRecipe.Factory<T> factory,
List<ItemLike> pIngredients, RecipeCategory pCategory, ItemLike pResult, float pExperience, int pCookingTime, String pGroup, String pRecipeName) {
for(ItemLike itemlike : pIngredients) {
SimpleCookingRecipeBuilder.generic(Ingredient.of(itemlike), pCategory, pResult, pExperience, pCookingTime, pCookingSerializer, factory).group(pGroup).unlockedBy(getHasName(itemlike), has(itemlike))
.save(recipeOutput, Aphelion.MOD_ID + ":" + getItemName(pResult) + pRecipeName + "_" + getItemName(itemlike));
}
}
}

View File

@@ -0,0 +1,20 @@
package net.xevianlight.aphelion.event;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
import net.xevianlight.aphelion.core.init.ModBlockEntities;
@EventBusSubscriber(modid = Aphelion.MOD_ID)
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);
}
}

View File

@@ -0,0 +1,92 @@
package net.xevianlight.aphelion.fluid;
import com.mojang.blaze3d.shaders.FogShape;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions;
import net.neoforged.neoforge.fluids.FluidType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
/**
* Basic implementation of {@link FluidType} that supports specifying still and flowing textures in the constructor.
*
* @author Choonster (<a href="https://github.com/Choonster-Minecraft-Mods/TestMod3/blob/1.19.x/LICENSE.txt">MIT License</a>)
* Change by: Kaupenjoe
* Added overlayTexture and tintColor as well. Also converts tint color into fog color
*/
public class BaseFluidType extends FluidType {
private final ResourceLocation stillTexture;
private final ResourceLocation flowingTexture;
private final ResourceLocation overlayTexture;
private final int tintColor;
private final Vector3f fogColor;
private float fogStart;
private float fogEnd;
public BaseFluidType(final ResourceLocation stillTexture, final ResourceLocation flowingTexture, final ResourceLocation overlayTexture,
final int tintColor, final Vector3f fogColor, final Properties properties) {
super(properties);
this.stillTexture = stillTexture;
this.flowingTexture = flowingTexture;
this.overlayTexture = overlayTexture;
this.tintColor = tintColor;
this.fogColor = fogColor;
fogStart = 1f;
fogEnd = 6f;
}
public BaseFluidType(final ResourceLocation stillTexture, final ResourceLocation flowingTexture, final ResourceLocation overlayTexture,
final int tintColor, final Vector3f fogColor, final Properties properties, float fogStart, float fogEnd) {
super(properties);
this.stillTexture = stillTexture;
this.flowingTexture = flowingTexture;
this.overlayTexture = overlayTexture;
this.tintColor = tintColor;
this.fogColor = fogColor;
this.fogStart = fogStart;
this.fogEnd = fogEnd;
}
public IClientFluidTypeExtensions getClientFluidTypeExtensions() {
return new IClientFluidTypeExtensions() {
@Override
public ResourceLocation getStillTexture() {
return stillTexture;
}
@Override
public ResourceLocation getFlowingTexture() {
return flowingTexture;
}
@Override
public @Nullable ResourceLocation getOverlayTexture() {
return overlayTexture;
}
@Override
public int getTintColor() {
return tintColor;
}
@Override
public @NotNull Vector3f modifyFogColor(Camera camera, float partialTick, ClientLevel level,
int renderDistance, float darkenWorldAmount, Vector3f fluidFogColor) {
return fogColor;
}
@Override
public void modifyFogRender(Camera camera, FogRenderer.FogMode mode, float renderDistance, float partialTick,
float nearDistance, float farDistance, FogShape shape) {
RenderSystem.setShaderFogStart(fogStart);
RenderSystem.setShaderFogEnd(fogEnd); // distance when the fog starts
}
};
}
}

View File

@@ -0,0 +1,35 @@
package net.xevianlight.aphelion.fluid;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.fluids.FluidType;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import net.xevianlight.aphelion.Aphelion;
import org.joml.Vector3f;
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 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
)
);
private static Supplier<FluidType> registerFluidType(String name, FluidType fluidType) {
return FLUID_TYPES.register(name, () -> fluidType);
}
public static void register(IEventBus eventBus) {
FLUID_TYPES.register(eventBus);
}
}

View File

@@ -0,0 +1,46 @@
package net.xevianlight.aphelion.fluid;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.BucketItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.fluids.BaseFlowingFluid;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.core.init.ModBlocks;
import net.xevianlight.aphelion.core.init.ModItems;
import java.util.function.Supplier;
public class ModFluids {
public static final DeferredRegister<Fluid> FLUIDS =
DeferredRegister.create(BuiltInRegistries.FLUID, Aphelion.MOD_ID);
public static final Supplier<FlowingFluid> SOURCE_OIL_FLUID = FLUIDS.register("oil",
() -> new BaseFlowingFluid.Source(ModFluids.OIL_PROPERTIES));
public static final Supplier<FlowingFluid> FLOWING_OIL_FLUID = FLUIDS.register("flowing_oil",
() -> new BaseFlowingFluid.Flowing(ModFluids.OIL_PROPERTIES));
public static final DeferredBlock<LiquidBlock> OIL_BLOCK = ModBlocks.BLOCKS.register("oil",
() -> new LiquidBlock(ModFluids.SOURCE_OIL_FLUID.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable()));
public static final DeferredItem<Item> OIL_BUCKET = ModItems.ITEMS.registerItem("oil_bucket",
properties -> new BucketItem(ModFluids.SOURCE_OIL_FLUID.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)
.slopeFindDistance(2).levelDecreasePerBlock(2).tickRate(10)
.block(ModFluids.OIL_BLOCK).bucket(ModFluids.OIL_BUCKET);
public static void register(IEventBus eventBus) {
FLUIDS.register(eventBus);
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotAluminum extends Item {
public IngotAluminum() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotCobalt extends Item {
public IngotCobalt() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotIridium extends Item {
public IngotIridium() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotNeodymium extends Item {
public IngotNeodymium() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotSteel extends Item {
public IngotSteel() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotTitanium extends Item {
public IngotTitanium() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotTungsten extends Item {
public IngotTungsten() {
super(new Properties());
}
}

View File

@@ -0,0 +1,9 @@
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;
public class IngotUranium extends Item {
public IngotUranium() {
super(new Properties());
}
}

View File

@@ -1,4 +1,4 @@
package net.xevianlight.extreme_rocketry.item;
package net.xevianlight.aphelion.item;
import net.minecraft.world.item.Item;

View File

@@ -0,0 +1,45 @@
package net.xevianlight.aphelion.mixins.common;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.LevelHeightAccessor;
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientLevel.ClientLevelData.class)
public abstract class ClientLevelMixin {
@Inject(method = "getHorizonHeight", at = @At("HEAD"), cancellable = true)
private void aphelion$horizonHeight(LevelHeightAccessor level, CallbackInfoReturnable<Double> cir) {
var mc = Minecraft.getInstance();
var clientLevel = mc.level;
if (clientLevel == null) return;
// effectsLocation is what your dimension JSON sets in "effects"
ResourceLocation effectsId = clientLevel.dimensionType().effectsLocation();
var i = DimensionRendererCache.getOrDefault(effectsId);
cir.setReturnValue((i == null) ? 1.0F : i.horizonHeight());
}
@Inject(method = "getClearColorScale", at = @At("HEAD"), cancellable = true)
private void aphelion$clearColorScale(CallbackInfoReturnable<Float> cir) {
var mc = Minecraft.getInstance();
var clientLevel = mc.level;
if (clientLevel == null) return;
ResourceLocation effectsId = clientLevel.dimensionType().effectsLocation();
var i = DimensionRendererCache.getOrDefault(effectsId);
cir.setReturnValue((i == null) ? 1.0F : i.clearColorScale());
}
}

View File

@@ -0,0 +1,24 @@
package net.xevianlight.aphelion.mixins.common;
import net.minecraft.client.renderer.DimensionSpecialEffects;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.dimension.DimensionType;
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
import net.xevianlight.aphelion.client.dimension.DimensionSkyEffects;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DimensionSpecialEffects.class)
public abstract class DimensionSpecialEffectsMixin {
@Inject(method = "forType", at = @At("HEAD"), cancellable = true)
private static void aphelion$forType(DimensionType type, CallbackInfoReturnable<DimensionSpecialEffects> cir) {
ResourceLocation effectsId = type.effectsLocation();
if (DimensionRendererCache.RENDERERS.containsKey(effectsId)) {
cir.setReturnValue(new DimensionSkyEffects(effectsId));
}
}
}

View File

@@ -0,0 +1,131 @@
package net.xevianlight.aphelion.screen;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.inventory.SimpleContainerData;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.neoforged.neoforge.items.SlotItemHandler;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
import net.xevianlight.aphelion.util.EnergyItemSlot;
import net.xevianlight.aphelion.util.ExtractOnlySlot;
import org.jetbrains.annotations.NotNull;
public class ElectricArcFurnaceMenu extends AbstractContainerMenu {
public final ElectricArcFurnaceEntity blockEntity;
private final Level level;
private final ContainerData data;
public ElectricArcFurnaceMenu(int i, Inventory inventory, FriendlyByteBuf extraData) {
this(i, inventory, inventory.player.level().getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(4));
}
public ElectricArcFurnaceMenu(int i, Inventory inventory, BlockEntity blockEntity, ContainerData data) {
super(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), i);
this.blockEntity = ((ElectricArcFurnaceEntity) blockEntity);
this.level = inventory.player.level();
this.data = data;
addPlayerInventory(inventory);
addPlayerHotbar(inventory);
this.addSlot(new EnergyItemSlot(this.blockEntity.inventory, 3, 8, 54));
this.addSlot(new SlotItemHandler(this.blockEntity.inventory, 0, 63, 35));
this.addSlot(new SlotItemHandler(this.blockEntity.inventory, 1, 40, 35));
this.addSlot(new ExtractOnlySlot(this.blockEntity.inventory, 2, 125, 35));
addDataSlots(data);
}
@Override
public boolean stillValid(Player player) {
return true;
}
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
// must assign a slot number to each of the slots used by the GUI.
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
private static final int HOTBAR_SLOT_COUNT = 9;
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
// THIS YOU HAVE TO DEFINE!
private static final int TE_INVENTORY_SLOT_COUNT = 3; // must be the number of slots you have!
@Override
public @NotNull ItemStack quickMoveStack(Player playerIn, int pIndex) {
Slot sourceSlot = slots.get(pIndex);
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
ItemStack sourceStack = sourceSlot.getItem();
ItemStack copyOfSourceStack = sourceStack.copy();
// Check if the slot clicked is one of the vanilla container slots
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
// This is a vanilla container slot so merge the stack into the tile inventory
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
+ TE_INVENTORY_SLOT_COUNT, false)) {
blockEntity.sendUpdate();
return ItemStack.EMPTY; // EMPTY_ITEM
}
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
// This is a TE slot so merge the stack into the players inventory
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
blockEntity.sendUpdate();
return ItemStack.EMPTY;
}
} else {
System.out.println("Invalid slotIndex:" + pIndex);
return ItemStack.EMPTY;
}
// If stack size == 0 (the entire stack was moved) set slot contents to null
if (sourceStack.getCount() == 0) {
sourceSlot.set(ItemStack.EMPTY);
blockEntity.sendUpdate();
} else {
blockEntity.sendUpdate();
sourceSlot.setChanged();
}
sourceSlot.onTake(playerIn, sourceStack);
blockEntity.sendUpdate();
return copyOfSourceStack;
}
public int getScaledArrowProgress() {
int progress = this.data.get(0);
int maxProgress = this.data.get(1);
int arrowPixelSize = 24;
return maxProgress != 0 && progress != 0 ? progress * arrowPixelSize / maxProgress : 0;
}
private void addPlayerInventory(Inventory playerInventory) {
for (int i = 0; i < 3; ++i) {
for (int l = 0; l < 9; ++l) {
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18));
}
}
}
private void addPlayerHotbar(Inventory playerInventory) {
for (int i = 0; i < 9; ++i) {
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
}
}
}

View File

@@ -0,0 +1,111 @@
package net.xevianlight.aphelion.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.xevianlight.aphelion.Aphelion;
import net.xevianlight.aphelion.screen.renderer.EnergyDisplayTooltipArea;
import net.xevianlight.aphelion.util.MouseUtil;
import java.util.Optional;
public class ElectricArcFurnaceScreen extends AbstractContainerScreen<ElectricArcFurnaceMenu> {
private static final ResourceLocation GUI_TEXTURE =
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "textures/gui/electric_arc_furnace/gui.png");
private static final ResourceLocation ARROW_TEXTURE =
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID,"textures/gui/base/arrow_progress.png");
private EnergyDisplayTooltipArea energyInfoArea;
public ElectricArcFurnaceScreen(ElectricArcFurnaceMenu menu, Inventory playerInventory, Component title) {
super(menu, playerInventory, title);
}
@Override
protected void init() {
super.init();
// Gets rid of labels
this.inventoryLabelY = 73;
this.titleLabelY = 5;
this.titleLabelX = 35;
assignEnergyInfoArea();
}
@Override
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
guiGraphics.blit(GUI_TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
renderProgressArrow(guiGraphics, x, y);
if (menu.blockEntity.getBlockState().getValue(BlockStateProperties.LIT)) {
guiGraphics.blit(GUI_TEXTURE, x + 54, y + 14, 176, 75, 13, 18);
}
renderEnergyBar(guiGraphics, x , y);
}
private void renderProgressArrow(GuiGraphics guiGraphics, int x, int y) {
guiGraphics.blit(ARROW_TEXTURE,x + 88, y + 35, 0, 0, menu.getScaledArrowProgress(), 16, 24, 16);
}
private void renderEnergyBar(GuiGraphics guiGraphics, int x, int y) {
int stored = menu.blockEntity.getEnergyStorage(null).getEnergyStored();
int max = menu.blockEntity.getEnergyStorage(null).getMaxEnergyStored();
int h = (max <= 0) ? 0 : (int) Math.round((stored / (double) max) * 42.0);
h = Math.max(0, Math.min(42, h));
int w = 14;
int drawX = x + 9;
int drawY = y + 9 + (42 - h); // move up as it fills
int u = 176;
int v = 15 + (42 - h); // sample lower part of bar texture
guiGraphics.blit(GUI_TEXTURE, drawX, drawY, u, v, w, h);
}
private void assignEnergyInfoArea() {
energyInfoArea = new EnergyDisplayTooltipArea(((width - imageWidth) / 2) + 9,
((height - imageHeight) / 2 ) + 9, menu.blockEntity.getEnergyStorage(null), 14, 42);
}
private void renderEnergyAreaTooltip(GuiGraphics guiGraphics, int pMouseX, int pMouseY, int x, int y) {
if(isMouseAboveArea(pMouseX, pMouseY, x, y, 9, 9, 14, 42)) {
guiGraphics.renderTooltip(this.font, energyInfoArea.getTooltips(),
Optional.empty(), pMouseX - x, pMouseY - y);
}
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
renderBackground(guiGraphics, mouseX, mouseY, delta);
super.render(guiGraphics, mouseX, mouseY, delta);
renderTooltip(guiGraphics, mouseX, mouseY);
}
@Override
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
super.renderLabels(guiGraphics, mouseX, mouseY);
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
renderEnergyAreaTooltip(guiGraphics, mouseX, mouseY, x, y);
}
public static boolean isMouseAboveArea(int pMouseX, int pMouseY, int x, int y, int offsetX, int offsetY, int width, int height) {
return MouseUtil.isMouseOver(pMouseX, pMouseY, x + offsetX, y + offsetY, width, height);
}
}

View File

@@ -0,0 +1,30 @@
package net.xevianlight.aphelion.screen;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
import net.neoforged.neoforge.network.IContainerFactory;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.aphelion.Aphelion;
public class ModMenuTypes {
public static final DeferredRegister<MenuType<?>> MENUS =
DeferredRegister.create(Registries.MENU, Aphelion.MOD_ID);
public static DeferredHolder<MenuType<?>,MenuType<TestBlockMenu>> TEST_BLOCK_MENU =
registerMenuType("test_block_menu", TestBlockMenu::new);
public static DeferredHolder<MenuType<?>,MenuType<ElectricArcFurnaceMenu>> ELECTRIC_ARC_FURNACE_MENU =
registerMenuType("electric_arc_furnace_menu", ElectricArcFurnaceMenu::new);
private static <T extends AbstractContainerMenu>DeferredHolder<MenuType<?>, MenuType<T>> registerMenuType(String name,
IContainerFactory<T> factory) {
return MENUS.register(name, () -> IMenuTypeExtension.create(factory));
}
public static void register(IEventBus eventBus) {
MENUS.register(eventBus);
}
}

View File

@@ -0,0 +1,107 @@
package net.xevianlight.aphelion.screen;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.neoforged.neoforge.items.SlotItemHandler;
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
import org.jetbrains.annotations.NotNull;
public class TestBlockMenu extends AbstractContainerMenu {
public final TestBlockEntity blockEntity;
private final Level level;
public TestBlockMenu(int i, Inventory inventory, FriendlyByteBuf extraData) {
this(i, inventory, inventory.player.level().getBlockEntity(extraData.readBlockPos()));
}
public TestBlockMenu(int i, Inventory inventory, BlockEntity blockEntity) {
super(ModMenuTypes.TEST_BLOCK_MENU.get(), i);
this.blockEntity = ((TestBlockEntity) blockEntity);
this.level = inventory.player.level();
addPlayerInventory(inventory);
addPlayerHotbar(inventory);
this.addSlot(new SlotItemHandler(this.blockEntity.inventory, 0, 80, 35));
}
@Override
public boolean stillValid(Player player) {
return true;
}
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
// must assign a slot number to each of the slots used by the GUI.
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
private static final int HOTBAR_SLOT_COUNT = 9;
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
// THIS YOU HAVE TO DEFINE!
private static final int TE_INVENTORY_SLOT_COUNT = 1; // must be the number of slots you have!
@Override
public @NotNull ItemStack quickMoveStack(Player playerIn, int pIndex) {
Slot sourceSlot = slots.get(pIndex);
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
ItemStack sourceStack = sourceSlot.getItem();
ItemStack copyOfSourceStack = sourceStack.copy();
// Check if the slot clicked is one of the vanilla container slots
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
// This is a vanilla container slot so merge the stack into the tile inventory
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
+ TE_INVENTORY_SLOT_COUNT, false)) {
blockEntity.sendUpdate();
return ItemStack.EMPTY; // EMPTY_ITEM
}
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
// This is a TE slot so merge the stack into the players inventory
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
blockEntity.sendUpdate();
return ItemStack.EMPTY;
}
} else {
System.out.println("Invalid slotIndex:" + pIndex);
return ItemStack.EMPTY;
}
// If stack size == 0 (the entire stack was moved) set slot contents to null
if (sourceStack.getCount() == 0) {
sourceSlot.set(ItemStack.EMPTY);
blockEntity.sendUpdate();
} else {
blockEntity.sendUpdate();
sourceSlot.setChanged();
}
sourceSlot.onTake(playerIn, sourceStack);
blockEntity.sendUpdate();
return copyOfSourceStack;
}
private void addPlayerInventory(Inventory playerInventory) {
for (int i = 0; i < 3; ++i) {
for (int l = 0; l < 9; ++l) {
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18));
}
}
}
private void addPlayerHotbar(Inventory playerInventory) {
for (int i = 0; i < 9; ++i) {
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
}
}
}

View File

@@ -0,0 +1,47 @@
package net.xevianlight.aphelion.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.xevianlight.aphelion.Aphelion;
public class TestBlockScreen extends AbstractContainerScreen<TestBlockMenu> {
private static final ResourceLocation GUI_TEXTURE =
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "textures/gui/test_block/gui.png");
public TestBlockScreen(TestBlockMenu menu, Inventory playerInventory, Component title) {
super(menu, playerInventory, title);
}
@Override
protected void init() {
super.init();
// Gets rid of labels
this.inventoryLabelY = 73;
this.titleLabelY = 5;
}
@Override
protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
pGuiGraphics.blit(GUI_TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
renderBackground(guiGraphics, mouseX, mouseY, delta);
super.render(guiGraphics, mouseX, mouseY, delta);
renderTooltip(guiGraphics, mouseX, mouseY);
}
}

View File

@@ -0,0 +1,46 @@
package net.xevianlight.aphelion.screen.renderer;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.neoforged.neoforge.energy.IEnergyStorage;
import java.util.List;
/*
* BluSunrize
* Copyright (c) 2021
*
* This code is licensed under "Blu's License of Common Sense"
* https://github.com/BluSunrize/ImmersiveEngineering/blob/1.19.2/LICENSE
*
* Slightly Modified Version by: Kaupenjoe
*/
public class EnergyDisplayTooltipArea {
private final int xPos;
private final int yPos;
private final int width;
private final int height;
private final IEnergyStorage energy;
public EnergyDisplayTooltipArea(int xMin, int yMin, IEnergyStorage energy) {
this(xMin, yMin, energy,8,64);
}
public EnergyDisplayTooltipArea(int xMin, int yMin, IEnergyStorage energy, int width, int height) {
xPos = xMin;
yPos = yMin;
this.width = width;
this.height = height;
this.energy = energy;
}
public List<Component> getTooltips() {
return List.of(Component.literal(energy.getEnergyStored()+" / "+energy.getMaxEnergyStored()+" FE"));
}
public void render(GuiGraphics guiGraphics) {
int stored = (int)(height * (energy.getEnergyStored() / (float)energy.getMaxEnergyStored()));
guiGraphics.fillGradient(xPos,yPos + (height - stored),xPos + width,
yPos + height,0xffb51500, 0xff600b00);
}
}

View File

@@ -0,0 +1,12 @@
package net.xevianlight.aphelion.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
public class Constants {
public static final Logger LOGGER = LogUtils.getLogger();
public static final Gson GSON = new Gson();
public static final Gson PRETTY_GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
}

View File

@@ -0,0 +1,19 @@
package net.xevianlight.aphelion.util;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.SlotItemHandler;
public class EnergyItemSlot extends SlotItemHandler {
public EnergyItemSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
super(itemHandler, index, xPosition, yPosition);
}
@Override
public boolean mayPlace(ItemStack stack) {
if (stack.getCapability(Capabilities.EnergyStorage.ITEM) != null)
return stack.getCapability(Capabilities.EnergyStorage.ITEM).canExtract();
return false;
}
}

View File

@@ -0,0 +1,16 @@
package net.xevianlight.aphelion.util;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.SlotItemHandler;
public class ExtractOnlySlot extends SlotItemHandler {
public ExtractOnlySlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
super(itemHandler, index, xPosition, yPosition);
}
@Override
public boolean mayPlace(ItemStack stack) {
return false;
}
}

View File

@@ -0,0 +1,49 @@
package net.xevianlight.aphelion.util;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.xevianlight.aphelion.Aphelion;
public class ModTags {
public static class Blocks {
private static TagKey<Block> createTag(String name) {
return BlockTags.create(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name));
}
public static final TagKey<Block> STORAGE_BLOCKS = commonTag("storage_blocks");
public static final TagKey<Block> STORAGE_BLOCKS_STEEL = commonTag("storage_blocks/steel");
private static TagKey<Block> commonTag(String name) {
return BlockTags.create(ResourceLocation.fromNamespaceAndPath("c", name));
}
}
public static class Items {
public static final TagKey<Item> TEST_TAG = createTag("test_tag");
public static final TagKey<Item> INGOTS = commonTag("ingots");
public static final TagKey<Item> STORAGE_BLOCKS = commonTag("storage_blocks");
public static final TagKey<Item> STORAGE_BLOCKS_STEEL = commonTag("storage_blocks/steel");
public static final TagKey<Item> INGOT_ALUMINUM = commonTag("ingots/aluminum");
public static final TagKey<Item> INGOT_STEEL = commonTag("ingots/steel");
public static final TagKey<Item> INGOT_TITANIUM = commonTag("ingots/titanium");
public static final TagKey<Item> INGOT_URANIUM = commonTag("ingots/uranium");
public static final TagKey<Item> INGOT_COBALT = commonTag("ingots/cobalt");
public static final TagKey<Item> INGOT_TUNGSTEN = commonTag("ingots/tungsten");
public static final TagKey<Item> INGOT_NEODYMIUM = commonTag("ingots/neodymium");
public static final TagKey<Item> INGOT_IRIDIUM = commonTag("ingots/iridium");
public static TagKey<Item> createTag(String name) {
return ItemTags.create(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name));
}
private static TagKey<Item> commonTag(String name) {
return ItemTags.create(ResourceLocation.fromNamespaceAndPath("c", name));
}
}
}

View File

@@ -0,0 +1,15 @@
package net.xevianlight.aphelion.util;
public class MouseUtil {
public static boolean isMouseOver(double mouseX, double mouseY, int x, int y) {
return isMouseOver(mouseX, mouseY, x, y, 16);
}
public static boolean isMouseOver(double mouseX, double mouseY, int x, int y, int size) {
return isMouseOver(mouseX, mouseY, x, y, size, size);
}
public static boolean isMouseOver(double mouseX, double mouseY, int x, int y, int sizeX, int sizeY) {
return (mouseX >= x && mouseX <= x + sizeX) && (mouseY >= y && mouseY <= y + sizeY);
}
}

View File

@@ -0,0 +1,64 @@
package net.xevianlight.aphelion.util;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.IItemHandlerModifiable;
public class SidedSlotHandler implements IItemHandler {
private final IItemHandlerModifiable backing;
private final int[] slots;
private final boolean allowInsert;
private final boolean allowExtract;
public SidedSlotHandler(IItemHandlerModifiable backing, int[] slots, boolean allowInsert, boolean allowExtract) {
this.backing = backing;
this.slots = slots;
this.allowInsert = allowInsert;
this.allowExtract = allowExtract;
}
private int toBackingSlot(int localSlot) {
if (localSlot < 0 || localSlot >= slots.length) return -1;
return slots[localSlot];
}
@Override
public int getSlots() {
return slots.length;
}
@Override
public ItemStack getStackInSlot(int slot) {
int s = toBackingSlot(slot);
return s < 0 ? ItemStack.EMPTY : backing.getStackInSlot(s);
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!allowInsert || stack.isEmpty()) return stack;
int s = toBackingSlot(slot);
return s < 0 ? stack : backing.insertItem(s, stack, simulate);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (!allowExtract || amount <= 0) return ItemStack.EMPTY;
int s = toBackingSlot(slot);
return s < 0 ? ItemStack.EMPTY : backing.extractItem(s, amount, simulate);
}
@Override
public int getSlotLimit(int slot) {
int s = toBackingSlot(slot);
return s < 0 ? 0 : backing.getSlotLimit(s);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
if (!allowInsert) return false;
int s = toBackingSlot(slot);
return s >= 0 && backing.isItemValid(s, stack);
}
}

View File

@@ -1,31 +0,0 @@
package net.xevianlight.extreme_rocketry;
import net.minecraft.client.Minecraft;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
// This class will not load on dedicated servers. Accessing client side code from here is safe.
@Mod(value = ExtremeRocketry.MOD_ID, dist = Dist.CLIENT)
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@EventBusSubscriber(modid = ExtremeRocketry.MOD_ID, value = Dist.CLIENT)
public class ExtremeRocketryClient {
public ExtremeRocketryClient(ModContainer container) {
// Allows NeoForge to create a config screen for this mod's configs.
// The config screen is accessed by going to the Mods screen > clicking on your mod > clicking on config.
// Do not forget to add translations for your config options to the en_us.json file.
container.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
}
@SubscribeEvent
static void onClientSetup(FMLClientSetupEvent event) {
// Some client setup code
ExtremeRocketry.LOGGER.info("HELLO FROM CLIENT SETUP");
ExtremeRocketry.LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName());
}
}

View File

@@ -1,35 +0,0 @@
package net.xevianlight.extreme_rocketry.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
public class TestBlock extends Block {
public TestBlock(Properties properties) {
super(properties);
}
public static Properties getProperties() {
return Properties
.of()
.sound(SoundType.ANVIL)
.destroyTime(2f)
.explosionResistance(10f)
.requiresCorrectToolForDrops();
}
public static Item.Properties getItemProperties() {
return new Item.Properties().stacksTo(3);
}
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
return InteractionResult.SUCCESS;
}
}

View File

@@ -1,13 +0,0 @@
package net.xevianlight.extreme_rocketry.core.init;
import net.minecraft.world.level.block.Block;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.extreme_rocketry.ExtremeRocketry;
import net.xevianlight.extreme_rocketry.block.TestBlock;
public class ModBlocks {
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(ExtremeRocketry.MOD_ID);
public static final DeferredBlock<Block> TEST_BLOCK = BLOCKS.register("test_block", () -> new TestBlock(TestBlock.getProperties()));
}

View File

@@ -1,30 +0,0 @@
package net.xevianlight.extreme_rocketry.core.init;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.extreme_rocketry.ExtremeRocketry;
import java.util.function.Supplier;
public class ModCreativeTabs {
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TAB = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, ExtremeRocketry.MOD_ID);
public static final Supplier<CreativeModeTab> EXTREME_ROCKETRY_ITEMS_TAB = CREATIVE_MODE_TAB.register("extreme_rocketry_items_tab",
() -> CreativeModeTab.builder().icon(() -> new ItemStack(ModItems.TEST_ITEM.get()))
.title(Component.translatable("creativetab.extreme_rocketry.extreme_rocketry_items"))
.displayItems((itemDisplayParameters, output) -> {
output.accept(ModItems.TEST_ITEM);
}).build());
public static final Supplier<CreativeModeTab> EXTREME_ROCKETRY_BLOCKS_TAB = CREATIVE_MODE_TAB.register("extreme_rocketry_blocks_tab",
() -> CreativeModeTab.builder().icon(() -> new ItemStack(ModItems.TEST_BLOCK.get()))
.withTabsBefore(ResourceLocation.fromNamespaceAndPath(ExtremeRocketry.MOD_ID, "extreme_rocketry_items_tab"))
.title(Component.translatable("creativetab.extreme_rocketry.extreme_rocketry_blocks"))
.displayItems((itemDisplayParameters, output) -> {
output.accept(ModItems.TEST_BLOCK);
}).build());
}

View File

@@ -1,20 +0,0 @@
package net.xevianlight.extreme_rocketry.core.init;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.xevianlight.extreme_rocketry.ExtremeRocketry;
import net.xevianlight.extreme_rocketry.block.TestBlock;
import net.xevianlight.extreme_rocketry.item.TestItem;
public class ModItems {
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(ExtremeRocketry.MOD_ID);
public static final DeferredItem<Item> TEST_ITEM = ITEMS.register("test_item", TestItem::new);
// Block Items
public static final DeferredItem<BlockItem> TEST_BLOCK = ITEMS.register("test_block", () -> new BlockItem(ModBlocks.TEST_BLOCK.get(), TestBlock.getItemProperties()));
}

View File

@@ -8,11 +8,11 @@
modLoader="javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the FML version. This is currently 2.
loaderVersion="${loader_version_range}" #mandatory
loaderVersion="[4,)" #mandatory
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license="${mod_license}"
license="GNU GPLv3"
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
@@ -21,13 +21,13 @@ license="${mod_license}"
[[mods]] #mandatory
# The modid of the mod
modId="${mod_id}" #mandatory
modId="aphelion" #mandatory
# The version number of the mod
version="${mod_version}" #mandatory
version="1.0.0" #mandatory
# A display name for the mod
displayName="${mod_name}" #mandatory
displayName="Aphelion" #mandatory
# A URL to query for updates for this mod. See the JSON update specification https://docs.neoforged.net/docs/misc/updatechecker/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
@@ -46,12 +46,12 @@ authors="XevianLight"
# The description text for the mod (multi line!) (#mandatory)
description='''
Extreme Rocketry!
Aphelion!
'''
# The [[mixins]] block allows you to declare your mixin config to FML so that it gets loaded.
#[[mixins]]
#config="${mod_id}.mixins.json"
[[mixins]]
config = "aphelion.mixins.json"
# The [[accessTransformers]] block allows you to declare where your AT file is.
# If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg
@@ -61,7 +61,7 @@ Extreme Rocketry!
# The coremods config file path is not configurable and is always loaded from META-INF/coremods.json
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies.${mod_id}]] #optional
[[dependencies.aphelion]] #optional
# the modid of the dependency
modId="neoforge" #mandatory
# The type of the dependency. Can be one of "required", "optional", "incompatible" or "discouraged" (case insensitive).
@@ -80,7 +80,7 @@ Extreme Rocketry!
side="BOTH"
# Here's another dependency
[[dependencies.${mod_id}]]
[[dependencies.aphelion]]
modId="minecraft"
type="required"
# This version range declares a minimum of the current minecraft version up to but not including the next major version

View File

@@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.xevianlight.aphelion.mixins",
"compatibilityLevel": "JAVA_21",
"mixins": [
],
"client": [
"common.ClientLevelMixin",
"common.DimensionSpecialEffectsMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -0,0 +1,14 @@
{
"custom_clouds": false,
"custom_sky": false,
"custom_weather": false,
"dimension": "aphelion:default",
"has_fog": false,
"has_thick_fog": true,
"render_in_rain": true,
"sunrise_angle": 0,
"sunrise_color": 14180147,
"render_void_fog": false,
"horizon_height": -128,
"clear_color_scale": 1.0
}

View File

@@ -0,0 +1,14 @@
{
"custom_clouds": false,
"custom_sky": false,
"custom_weather": false,
"dimension": "aphelion:earth",
"has_fog": false,
"has_thick_fog": false,
"render_in_rain": true,
"sunrise_angle": 0,
"sunrise_color": 14180147,
"render_void_fog": false,
"horizon_height": -128,
"clear_color_scale": 1.0
}

View File

@@ -0,0 +1,14 @@
{
"custom_clouds": false,
"custom_sky": true,
"custom_weather": false,
"dimension": "aphelion:mars",
"has_fog": false,
"has_thick_fog": false,
"render_in_rain": true,
"sunrise_angle": 0,
"sunrise_color": 14180147,
"render_void_fog": false,
"horizon_height": -128,
"clear_color_scale": 1.0
}

View File

@@ -0,0 +1,14 @@
{
"custom_clouds": false,
"custom_sky": false,
"custom_weather": false,
"dimension": "aphelion:venus",
"has_fog": false,
"has_thick_fog": true,
"render_in_rain": true,
"sunrise_angle": 0,
"sunrise_color": 14180147,
"render_void_fog": false,
"horizon_height": -128,
"clear_color_scale": 1.0
}

View File

@@ -0,0 +1,14 @@
{
"custom_clouds": false,
"custom_sky": true,
"custom_weather": false,
"dimension": "aphelion:test",
"has_fog": false,
"has_thick_fog": true,
"render_in_rain": true,
"sunrise_angle": 0,
"sunrise_color": 14180147,
"render_void_fog": false,
"horizon_height": -128,
"clear_color_scale": 1.0
}

View File

@@ -0,0 +1,28 @@
{
"item.aphelion.test_item": "Test Item",
"block.aphelion.test_block": "Test Block",
"block.aphelion.electric_arc_furnace": "Electric Arc Furnace",
"item.aphelion.ingot_steel": "Steel Ingot",
"block.aphelion.block_steel": "Steel Block",
"block.aphelion.oil": "Oil",
"item.aphelion.ingot_aluminum": "Aluminum Ingot",
"item.aphelion.ingot_tungsten": "Tungsten Ingot",
"item.aphelion.ingot_titanium": "Titanium Ingot",
"item.aphelion.ingot_uranium": "Uranium Ingot",
"item.aphelion.ingot_cobalt": "Cobalt Ingot",
"item.aphelion.ingot_neodymium": "Neodymium Ingot",
"item.aphelion.ingot_iridium": "Iridium Ingot",
"item.aphelion.oil_bucket": "Oil Bucket",
"item.aphelion.music_disc_bit_shift": "Music Disc",
"item.aphelion.music_disc_bit_shift.desc": "XevianLight - Bit Shift",
"creativetab.aphelion.aphelion_items": "Aphelion Items",
"creativetab.aphelion.aphelion_blocks": "Aphelion Blocks",
"tag.item.c.ingots.steel": "Steel Ingots",
"tag.item.c.ingots.aluminum": "Aluminum Ingots"
}

View File

@@ -0,0 +1,10 @@
{
"bit_shift": {
"sounds": [
{
"name": "aphelion:bit_shift",
"stream": true
}
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

View File

@@ -1,7 +0,0 @@
{
"variants": {
"": {
"model": "extreme_rocketry:block/test_block"
}
}
}

View File

@@ -1,7 +0,0 @@
{
"item.extreme_rocketry.test_item": "Test Item",
"block.extreme_rocketry.test_block": "Test Block",
"creativetab.extreme_rocketry.extreme_rocketry_items": "Extreme Rocketry Items",
"creativetab.extreme_rocketry.extreme_rocketry_blocks": "Extreme Rocketry Blocks"
}

View File

@@ -1,6 +0,0 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "extreme_rocketry:block/test_block"
}
}

View File

@@ -1,3 +0,0 @@
{
"parent": "extreme_rocketry:block/test_block"
}

Some files were not shown because too many files have changed in this diff Show More