diff --git a/gradle.properties b/gradle.properties index 526c770..72abe8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/main/java/net/xevianlight/extreme_rocketry/ExtremeRocketry.java b/src/main/java/net/xevianlight/aphelion/Aphelion.java similarity index 50% rename from src/main/java/net/xevianlight/extreme_rocketry/ExtremeRocketry.java rename to src/main/java/net/xevianlight/aphelion/Aphelion.java index 434ea08..4f03efa 100644 --- a/src/main/java/net/xevianlight/extreme_rocketry/ExtremeRocketry.java +++ b/src/main/java/net/xevianlight/aphelion/Aphelion.java @@ -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); + } } } diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/BlockSteel.java b/src/main/java/net/xevianlight/aphelion/block/custom/BlockSteel.java new file mode 100644 index 0000000..a1eac60 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/custom/BlockSteel.java @@ -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(); + } + +} diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/DimensionChangerBlock.java b/src/main/java/net/xevianlight/aphelion/block/custom/DimensionChangerBlock.java new file mode 100644 index 0000000..920dcda --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/custom/DimensionChangerBlock.java @@ -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 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/ElectricArcFurnace.java b/src/main/java/net/xevianlight/aphelion/block/custom/ElectricArcFurnace.java new file mode 100644 index 0000000..889e436 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/custom/ElectricArcFurnace.java @@ -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 CODEC = simpleCodec(ElectricArcFurnace::new); + + @Override + protected MapCodec 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 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 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 BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType 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 builder) { + builder.add(FACING, LIT); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/custom/TestBlock.java b/src/main/java/net/xevianlight/aphelion/block/custom/TestBlock.java new file mode 100644 index 0000000..b29ba2d --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/custom/TestBlock.java @@ -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 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 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 slots = new ArrayList<>(); + slots.add(0); + TestBlockEntity testBlockEntity = ((TestBlockEntity) level.getBlockEntity(pos)); + return getRedstoneSignalFromItemHandler(testBlockEntity.inventory, slots); + } + + @Override + public @Nullable BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType blockEntityType) { + if (level.isClientSide) { + return null; + } + return createTickerHelper(blockEntityType, ModBlockEntities.TEST_BLOCK_ENTITY.get(), (level1, blockPos, blockState, testBlockEntity) -> testBlockEntity.tick(level1, blockPos, blockState)); + + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/DimensionChangerBlockEntity.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/DimensionChangerBlockEntity.java new file mode 100644 index 0000000..de081e0 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/DimensionChangerBlockEntity.java @@ -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 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java new file mode 100644 index 0000000..500ede1 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/ElectricArcFurnaceEntity.java @@ -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> 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> 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> 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 getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider pRegistries) { + return saveWithoutMetadata(pRegistries); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/TestBlockEntity.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/TestBlockEntity.java new file mode 100644 index 0000000..6564441 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/TestBlockEntity.java @@ -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 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/custom/TestBlockEntity2.java b/src/main/java/net/xevianlight/aphelion/block/entity/custom/TestBlockEntity2.java new file mode 100644 index 0000000..cd266f7 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/custom/TestBlockEntity2.java @@ -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 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 getItems() { + return items; + } + + // The setter for our item stack list. + @Override + protected void setItems(NonNullList 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); + } + } +} diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java b/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java new file mode 100644 index 0000000..3ba83df --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyStorage.java @@ -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(); + } + diff --git a/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyUtil.java b/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyUtil.java new file mode 100644 index 0000000..0eaac40 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/block/entity/energy/ModEnergyUtil.java @@ -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; + } +} diff --git a/src/main/java/net/xevianlight/aphelion/client/AphelionClient.java b/src/main/java/net/xevianlight/aphelion/client/AphelionClient.java new file mode 100644 index 0000000..cf23b43 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/AphelionClient.java @@ -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 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() + ); + } +} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/Config.java b/src/main/java/net/xevianlight/aphelion/client/AphelionConfig.java similarity index 89% rename from src/main/java/net/xevianlight/extreme_rocketry/Config.java rename to src/main/java/net/xevianlight/aphelion/client/AphelionConfig.java index b4ee23b..88ce6a4 100644 --- a/src/main/java/net/xevianlight/extreme_rocketry/Config.java +++ b/src/main/java/net/xevianlight/aphelion/client/AphelionConfig.java @@ -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> 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)); diff --git a/src/main/java/net/xevianlight/aphelion/client/AphelionDebugOverlay.java b/src/main/java/net/xevianlight/aphelion/client/AphelionDebugOverlay.java new file mode 100644 index 0000000..58459be --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/AphelionDebugOverlay.java @@ -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) + ? "" + : ("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); + } +} \ No newline at end of file diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/AphelionDimensionRenderers.java b/src/main/java/net/xevianlight/aphelion/client/dimension/AphelionDimensionRenderers.java new file mode 100644 index 0000000..c6d5413 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/AphelionDimensionRenderers.java @@ -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 object, + ResourceManager resourceManager, + ProfilerFiller profiler) { + + Map 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionRenderer.java b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionRenderer.java new file mode 100644 index 0000000..f7a63c5 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionRenderer.java @@ -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 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 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)); +} diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionRendererCache.java b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionRendererCache.java new file mode 100644 index 0000000..1328acf --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionRendererCache.java @@ -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 RENDERERS = new HashMap<>(); + + public static void registerPlanetRenderers(Map renderers) { + RENDERERS.clear(); + RENDERERS.putAll(renderers); + + } + + public static DimensionRenderer getOrDefault(ResourceLocation id) { + return RENDERERS.getOrDefault(id, null); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionSkyEffects.java b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionSkyEffects.java new file mode 100644 index 0000000..d2a225c --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionSkyEffects.java @@ -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}; + } + +} + diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionSkyRenderer.java b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionSkyRenderer.java new file mode 100644 index 0000000..d024d47 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/DimensionSkyRenderer.java @@ -0,0 +1,9 @@ +package net.xevianlight.aphelion.client.dimension; + +public class DimensionSkyRenderer { + + DimensionRenderer renderer; + + DimensionSkyRenderer(DimensionRenderer renderer) { this.renderer = renderer; } + +} diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/OrbitSkyDefinition.java b/src/main/java/net/xevianlight/aphelion/client/dimension/OrbitSkyDefinition.java new file mode 100644 index 0000000..b33f7d1 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/OrbitSkyDefinition.java @@ -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 + +) { + +} diff --git a/src/main/java/net/xevianlight/aphelion/client/dimension/SpaceSkyEffects.java b/src/main/java/net/xevianlight/aphelion/client/dimension/SpaceSkyEffects.java new file mode 100644 index 0000000..5d9b24e --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/client/dimension/SpaceSkyEffects.java @@ -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"); + } +} + diff --git a/src/main/java/net/xevianlight/aphelion/core/init/ModBlockEntities.java b/src/main/java/net/xevianlight/aphelion/core/init/ModBlockEntities.java new file mode 100644 index 0000000..de1b8ec --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/core/init/ModBlockEntities.java @@ -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> BLOCK_ENTITIES = DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, Aphelion.MOD_ID); + + public static final Supplier> TEST_BLOCK_ENTITY = + BLOCK_ENTITIES.register("test_block_entity", () -> BlockEntityType.Builder.of( + TestBlockEntity::new, ModBlocks.TEST_BLOCK.get()).build(null) + ); + + public static final Supplier> 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> ELECTRIC_ARC_FURNACE_ENTITY = + BLOCK_ENTITIES.register("electric_arc_furnace_block_entity", () -> BlockEntityType.Builder.of( + ElectricArcFurnaceEntity::new, ModBlocks.ELECTRIC_ARC_FURNACE.get()).build(null) + ); +} diff --git a/src/main/java/net/xevianlight/aphelion/core/init/ModBlocks.java b/src/main/java/net/xevianlight/aphelion/core/init/ModBlocks.java new file mode 100644 index 0000000..ae0d9d0 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/core/init/ModBlocks.java @@ -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 TEST_BLOCK = BLOCKS.register("test_block", () -> new TestBlock(TestBlock.getProperties())); + public static final DeferredBlock BLOCK_STEEL = BLOCKS.register("block_steel", () -> new BlockSteel(BlockSteel.getProperties())); + public static final DeferredBlock DIMENSION_CHANGER = BLOCKS.register("dimension_changer", () -> new DimensionChangerBlock(DimensionChangerBlock.getProperties())); + public static final DeferredBlock ELECTRIC_ARC_FURNACE = BLOCKS.register("electric_arc_furnace", () -> new ElectricArcFurnace(ElectricArcFurnace.getProperties())); +} diff --git a/src/main/java/net/xevianlight/aphelion/core/init/ModCreativeTabs.java b/src/main/java/net/xevianlight/aphelion/core/init/ModCreativeTabs.java new file mode 100644 index 0000000..27cedcb --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/core/init/ModCreativeTabs.java @@ -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 CREATIVE_MODE_TAB = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Aphelion.MOD_ID); + + public static final Supplier 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 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()); +} diff --git a/src/main/java/net/xevianlight/aphelion/core/init/ModItems.java b/src/main/java/net/xevianlight/aphelion/core/init/ModItems.java new file mode 100644 index 0000000..bdd7bb3 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/core/init/ModItems.java @@ -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 TEST_ITEM = ITEMS.register("test_item", TestItem::new); + public static final DeferredItem INGOT_ALUMINUM = ITEMS.register("ingot_aluminum", IngotAluminum::new); + public static final DeferredItem INGOT_STEEL = ITEMS.register("ingot_steel", IngotSteel::new); + public static final DeferredItem INGOT_TITANIUM = ITEMS.register("ingot_titanium", IngotTitanium::new); + public static final DeferredItem INGOT_URANIUM = ITEMS.register("ingot_uranium", IngotUranium::new); + public static final DeferredItem INGOT_COBALT = ITEMS.register("ingot_cobalt", IngotCobalt::new); + public static final DeferredItem INGOT_TUNGSTEN = ITEMS.register("ingot_tungsten", IngotTungsten::new); + public static final DeferredItem INGOT_NEODYMIUM = ITEMS.register("ingot_neodymium", IngotNeodymium::new); + public static final DeferredItem INGOT_IRIDIUM = ITEMS.register("ingot_iridium", IngotIridium::new); + +public static final DeferredItem 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 TEST_BLOCK = ITEMS.register("test_block", () -> new BlockItem(ModBlocks.TEST_BLOCK.get(), TestBlock.getItemProperties().stacksTo(9999))); + public static final DeferredItem DIMENSION_CHANGER = ITEMS.register("dimension_changer", () -> new BlockItem(ModBlocks.DIMENSION_CHANGER.get(), DimensionChangerBlock.getItemProperties())); + public static final DeferredItem ELECTRIC_ARC_FURNACE = ITEMS.register("electric_arc_furnace", () -> new BlockItem(ModBlocks.ELECTRIC_ARC_FURNACE.get(), ElectricArcFurnace.getItemProperties())); + public static final DeferredItem BLOCK_STEEL = ITEMS.register("block_steel", () -> new BlockItem(ModBlocks.BLOCK_STEEL.get(), BlockSteel.getItemProperties())); +} diff --git a/src/main/java/net/xevianlight/aphelion/core/init/ModSounds.java b/src/main/java/net/xevianlight/aphelion/core/init/ModSounds.java new file mode 100644 index 0000000..f175133 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/core/init/ModSounds.java @@ -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 SOUND_EVENTS = + DeferredRegister.create(Registries.SOUND_EVENT, Aphelion.MOD_ID); + + private static ResourceKey createSong(String name) { + return ResourceKey.create(Registries.JUKEBOX_SONG, ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name)); + } + + public static final Supplier BIT_SHIFT = registerSoundEvent("bit_shift"); + public static final ResourceKey BIT_SHIFT_KEY = createSong("bit_shift"); + + private static Supplier 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/DataGenerators.java b/src/main/java/net/xevianlight/aphelion/datagen/DataGenerators.java new file mode 100644 index 0000000..e425dd6 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/DataGenerators.java @@ -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 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)); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModBlockLootTableProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModBlockLootTableProvider.java new file mode 100644 index 0000000..3eb88f1 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModBlockLootTableProvider.java @@ -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 getKnownBlocks() { + return ModBlocks.BLOCKS.getEntries().stream().map(Holder::value)::iterator; + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModBlockStateProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModBlockStateProvider.java new file mode 100644 index 0000000..335889f --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModBlockStateProvider.java @@ -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 deferredBlock) { + simpleBlockItem(deferredBlock.get(), new ModelFile.UncheckedModelFile("aphelion:block/" + deferredBlock.getId().getPath())); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModBlockTagProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModBlockTagProvider.java new file mode 100644 index 0000000..56ab36a --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModBlockTagProvider.java @@ -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 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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModDataMapProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModDataMapProvider.java new file mode 100644 index 0000000..951c342 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModDataMapProvider.java @@ -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 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModFluidTagsProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModFluidTagsProvider.java new file mode 100644 index 0000000..8d590e2 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModFluidTagsProvider.java @@ -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 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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModItemModelProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModItemModelProvider.java new file mode 100644 index 0000000..eaa7dd4 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModItemModelProvider.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModItemTagProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModItemTagProvider.java new file mode 100644 index 0000000..6955e46 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModItemTagProvider.java @@ -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 lookupProvider, CompletableFuture> 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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/datagen/ModRecipeProvider.java b/src/main/java/net/xevianlight/aphelion/datagen/ModRecipeProvider.java new file mode 100644 index 0000000..a6fa893 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/datagen/ModRecipeProvider.java @@ -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 registries) { + super(output, registries); + } + + @Override + protected void buildRecipes(RecipeOutput recipeOutput) { + + List 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 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 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 void oreCooking(RecipeOutput recipeOutput, RecipeSerializer pCookingSerializer, AbstractCookingRecipe.Factory factory, + List 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)); + } + } +} diff --git a/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java b/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java new file mode 100644 index 0000000..b1904a3 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/event/ModBusEvents.java @@ -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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/fluid/BaseFluidType.java b/src/main/java/net/xevianlight/aphelion/fluid/BaseFluidType.java new file mode 100644 index 0000000..3675871 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/fluid/BaseFluidType.java @@ -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 (MIT License) + * 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 + } + }; + } +} diff --git a/src/main/java/net/xevianlight/aphelion/fluid/ModFluidTypes.java b/src/main/java/net/xevianlight/aphelion/fluid/ModFluidTypes.java new file mode 100644 index 0000000..61c6435 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/fluid/ModFluidTypes.java @@ -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 FLUID_TYPES = + DeferredRegister.create(NeoForgeRegistries.Keys.FLUID_TYPES, Aphelion.MOD_ID); + + public static final Supplier 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 registerFluidType(String name, FluidType fluidType) { + return FLUID_TYPES.register(name, () -> fluidType); + } + + public static void register(IEventBus eventBus) { + FLUID_TYPES.register(eventBus); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java b/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java new file mode 100644 index 0000000..9580e5a --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/fluid/ModFluids.java @@ -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 FLUIDS = + DeferredRegister.create(BuiltInRegistries.FLUID, Aphelion.MOD_ID); + + public static final Supplier SOURCE_OIL_FLUID = FLUIDS.register("oil", + () -> new BaseFlowingFluid.Source(ModFluids.OIL_PROPERTIES)); + public static final Supplier FLOWING_OIL_FLUID = FLUIDS.register("flowing_oil", + () -> new BaseFlowingFluid.Flowing(ModFluids.OIL_PROPERTIES)); + + public static final DeferredBlock OIL_BLOCK = ModBlocks.BLOCKS.register("oil", + () -> new LiquidBlock(ModFluids.SOURCE_OIL_FLUID.get(), BlockBehaviour.Properties.ofFullCopy(Blocks.WATER).noLootTable())); + + public static final DeferredItem OIL_BUCKET = ModItems.ITEMS.registerItem("oil_bucket", + properties -> new BucketItem(ModFluids.SOURCE_OIL_FLUID.get(), properties.stacksTo(1).craftRemainder(Items.BUCKET))); + + 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotAluminum.java b/src/main/java/net/xevianlight/aphelion/item/IngotAluminum.java new file mode 100644 index 0000000..3268a36 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotAluminum.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotCobalt.java b/src/main/java/net/xevianlight/aphelion/item/IngotCobalt.java new file mode 100644 index 0000000..afad691 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotCobalt.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotIridium.java b/src/main/java/net/xevianlight/aphelion/item/IngotIridium.java new file mode 100644 index 0000000..0a46fde --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotIridium.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotNeodymium.java b/src/main/java/net/xevianlight/aphelion/item/IngotNeodymium.java new file mode 100644 index 0000000..5a07b41 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotNeodymium.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotSteel.java b/src/main/java/net/xevianlight/aphelion/item/IngotSteel.java new file mode 100644 index 0000000..ae310aa --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotSteel.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotTitanium.java b/src/main/java/net/xevianlight/aphelion/item/IngotTitanium.java new file mode 100644 index 0000000..d31f35b --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotTitanium.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotTungsten.java b/src/main/java/net/xevianlight/aphelion/item/IngotTungsten.java new file mode 100644 index 0000000..8ad88e9 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotTungsten.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/item/IngotUranium.java b/src/main/java/net/xevianlight/aphelion/item/IngotUranium.java new file mode 100644 index 0000000..b6f9bad --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/item/IngotUranium.java @@ -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()); + } +} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/item/TestItem.java b/src/main/java/net/xevianlight/aphelion/item/TestItem.java similarity index 75% rename from src/main/java/net/xevianlight/extreme_rocketry/item/TestItem.java rename to src/main/java/net/xevianlight/aphelion/item/TestItem.java index 53ff6a1..13f9125 100644 --- a/src/main/java/net/xevianlight/extreme_rocketry/item/TestItem.java +++ b/src/main/java/net/xevianlight/aphelion/item/TestItem.java @@ -1,4 +1,4 @@ -package net.xevianlight.extreme_rocketry.item; +package net.xevianlight.aphelion.item; import net.minecraft.world.item.Item; diff --git a/src/main/java/net/xevianlight/aphelion/mixins/common/ClientLevelMixin.java b/src/main/java/net/xevianlight/aphelion/mixins/common/ClientLevelMixin.java new file mode 100644 index 0000000..54cb491 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/mixins/common/ClientLevelMixin.java @@ -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 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 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()); + } +} \ No newline at end of file diff --git a/src/main/java/net/xevianlight/aphelion/mixins/common/DimensionSpecialEffectsMixin.java b/src/main/java/net/xevianlight/aphelion/mixins/common/DimensionSpecialEffectsMixin.java new file mode 100644 index 0000000..3b4f0eb --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/mixins/common/DimensionSpecialEffectsMixin.java @@ -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 cir) { + ResourceLocation effectsId = type.effectsLocation(); + + if (DimensionRendererCache.RENDERERS.containsKey(effectsId)) { + cir.setReturnValue(new DimensionSkyEffects(effectsId)); + } + } +} diff --git a/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java new file mode 100644 index 0000000..7ff2bc2 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceMenu.java @@ -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)); + } + } +} diff --git a/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java new file mode 100644 index 0000000..48192ba --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/screen/ElectricArcFurnaceScreen.java @@ -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 { + + 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/screen/ModMenuTypes.java b/src/main/java/net/xevianlight/aphelion/screen/ModMenuTypes.java new file mode 100644 index 0000000..e8be88a --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/screen/ModMenuTypes.java @@ -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> MENUS = + DeferredRegister.create(Registries.MENU, Aphelion.MOD_ID); + + public static DeferredHolder,MenuType> TEST_BLOCK_MENU = + registerMenuType("test_block_menu", TestBlockMenu::new); + public static DeferredHolder,MenuType> ELECTRIC_ARC_FURNACE_MENU = + registerMenuType("electric_arc_furnace_menu", ElectricArcFurnaceMenu::new); + + private static DeferredHolder, MenuType> registerMenuType(String name, + IContainerFactory factory) { + return MENUS.register(name, () -> IMenuTypeExtension.create(factory)); + } + + public static void register(IEventBus eventBus) { + MENUS.register(eventBus); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/screen/TestBlockMenu.java b/src/main/java/net/xevianlight/aphelion/screen/TestBlockMenu.java new file mode 100644 index 0000000..4cea62c --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/screen/TestBlockMenu.java @@ -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)); + } + } +} diff --git a/src/main/java/net/xevianlight/aphelion/screen/TestBlockScreen.java b/src/main/java/net/xevianlight/aphelion/screen/TestBlockScreen.java new file mode 100644 index 0000000..b44caa1 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/screen/TestBlockScreen.java @@ -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 { + + 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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/screen/renderer/EnergyDisplayTooltipArea.java b/src/main/java/net/xevianlight/aphelion/screen/renderer/EnergyDisplayTooltipArea.java new file mode 100644 index 0000000..ad8380d --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/screen/renderer/EnergyDisplayTooltipArea.java @@ -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 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); + } +} \ No newline at end of file diff --git a/src/main/java/net/xevianlight/aphelion/util/Constants.java b/src/main/java/net/xevianlight/aphelion/util/Constants.java new file mode 100644 index 0000000..ee1fde7 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/util/Constants.java @@ -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(); +} diff --git a/src/main/java/net/xevianlight/aphelion/util/EnergyItemSlot.java b/src/main/java/net/xevianlight/aphelion/util/EnergyItemSlot.java new file mode 100644 index 0000000..810e52e --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/util/EnergyItemSlot.java @@ -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; + } +} diff --git a/src/main/java/net/xevianlight/aphelion/util/ExtractOnlySlot.java b/src/main/java/net/xevianlight/aphelion/util/ExtractOnlySlot.java new file mode 100644 index 0000000..bf1e610 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/util/ExtractOnlySlot.java @@ -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; + } +} diff --git a/src/main/java/net/xevianlight/aphelion/util/ModTags.java b/src/main/java/net/xevianlight/aphelion/util/ModTags.java new file mode 100644 index 0000000..5a2b675 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/util/ModTags.java @@ -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 createTag(String name) { + return BlockTags.create(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name)); + } + + public static final TagKey STORAGE_BLOCKS = commonTag("storage_blocks"); + public static final TagKey STORAGE_BLOCKS_STEEL = commonTag("storage_blocks/steel"); + + private static TagKey commonTag(String name) { + return BlockTags.create(ResourceLocation.fromNamespaceAndPath("c", name)); + } + } + + public static class Items { + public static final TagKey TEST_TAG = createTag("test_tag"); + public static final TagKey INGOTS = commonTag("ingots"); + + public static final TagKey STORAGE_BLOCKS = commonTag("storage_blocks"); + public static final TagKey STORAGE_BLOCKS_STEEL = commonTag("storage_blocks/steel"); + public static final TagKey INGOT_ALUMINUM = commonTag("ingots/aluminum"); + public static final TagKey INGOT_STEEL = commonTag("ingots/steel"); + public static final TagKey INGOT_TITANIUM = commonTag("ingots/titanium"); + public static final TagKey INGOT_URANIUM = commonTag("ingots/uranium"); + public static final TagKey INGOT_COBALT = commonTag("ingots/cobalt"); + public static final TagKey INGOT_TUNGSTEN = commonTag("ingots/tungsten"); + public static final TagKey INGOT_NEODYMIUM = commonTag("ingots/neodymium"); + public static final TagKey INGOT_IRIDIUM = commonTag("ingots/iridium"); + + public static TagKey createTag(String name) { + return ItemTags.create(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, name)); + } + + private static TagKey commonTag(String name) { + return ItemTags.create(ResourceLocation.fromNamespaceAndPath("c", name)); + } + + } +} diff --git a/src/main/java/net/xevianlight/aphelion/util/MouseUtil.java b/src/main/java/net/xevianlight/aphelion/util/MouseUtil.java new file mode 100644 index 0000000..fab1a6d --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/util/MouseUtil.java @@ -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); + } +} diff --git a/src/main/java/net/xevianlight/aphelion/util/SidedSlotHandler.java b/src/main/java/net/xevianlight/aphelion/util/SidedSlotHandler.java new file mode 100644 index 0000000..5675892 --- /dev/null +++ b/src/main/java/net/xevianlight/aphelion/util/SidedSlotHandler.java @@ -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); + } +} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/ExtremeRocketryClient.java b/src/main/java/net/xevianlight/extreme_rocketry/ExtremeRocketryClient.java deleted file mode 100644 index 9ed74c4..0000000 --- a/src/main/java/net/xevianlight/extreme_rocketry/ExtremeRocketryClient.java +++ /dev/null @@ -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()); - } -} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/block/TestBlock.java b/src/main/java/net/xevianlight/extreme_rocketry/block/TestBlock.java deleted file mode 100644 index 25d38a6..0000000 --- a/src/main/java/net/xevianlight/extreme_rocketry/block/TestBlock.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModBlocks.java b/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModBlocks.java deleted file mode 100644 index c7c3f39..0000000 --- a/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModBlocks.java +++ /dev/null @@ -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 TEST_BLOCK = BLOCKS.register("test_block", () -> new TestBlock(TestBlock.getProperties())); -} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModCreativeTabs.java b/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModCreativeTabs.java deleted file mode 100644 index 1d6f9cb..0000000 --- a/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModCreativeTabs.java +++ /dev/null @@ -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 CREATIVE_MODE_TAB = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, ExtremeRocketry.MOD_ID); - - public static final Supplier 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 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()); -} diff --git a/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModItems.java b/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModItems.java deleted file mode 100644 index be01929..0000000 --- a/src/main/java/net/xevianlight/extreme_rocketry/core/init/ModItems.java +++ /dev/null @@ -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 TEST_ITEM = ITEMS.register("test_item", TestItem::new); - - - // Block Items - - public static final DeferredItem TEST_BLOCK = ITEMS.register("test_block", () -> new BlockItem(ModBlocks.TEST_BLOCK.get(), TestBlock.getItemProperties())); -} diff --git a/src/main/templates/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml similarity index 92% rename from src/main/templates/META-INF/neoforge.mods.toml rename to src/main/resources/META-INF/neoforge.mods.toml index bcdaccd..0ba7281 100644 --- a/src/main/templates/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -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 diff --git a/src/main/resources/aphelion.mixins.json b/src/main/resources/aphelion.mixins.json new file mode 100644 index 0000000..37514cb --- /dev/null +++ b/src/main/resources/aphelion.mixins.json @@ -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 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/dimension_renderers/orbit/default.json b/src/main/resources/assets/aphelion/dimension_renderers/orbit/default.json new file mode 100644 index 0000000..d79a80c --- /dev/null +++ b/src/main/resources/assets/aphelion/dimension_renderers/orbit/default.json @@ -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 +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/dimension_renderers/orbit/earth.json b/src/main/resources/assets/aphelion/dimension_renderers/orbit/earth.json new file mode 100644 index 0000000..1d3dca5 --- /dev/null +++ b/src/main/resources/assets/aphelion/dimension_renderers/orbit/earth.json @@ -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 +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/dimension_renderers/orbit/mars.json b/src/main/resources/assets/aphelion/dimension_renderers/orbit/mars.json new file mode 100644 index 0000000..bb02aed --- /dev/null +++ b/src/main/resources/assets/aphelion/dimension_renderers/orbit/mars.json @@ -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 +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/dimension_renderers/orbit/venus.json b/src/main/resources/assets/aphelion/dimension_renderers/orbit/venus.json new file mode 100644 index 0000000..3235008 --- /dev/null +++ b/src/main/resources/assets/aphelion/dimension_renderers/orbit/venus.json @@ -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 +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/dimension_renderers/test.json b/src/main/resources/assets/aphelion/dimension_renderers/test.json new file mode 100644 index 0000000..5c99798 --- /dev/null +++ b/src/main/resources/assets/aphelion/dimension_renderers/test.json @@ -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 +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/lang/en_us.json b/src/main/resources/assets/aphelion/lang/en_us.json new file mode 100644 index 0000000..070f454 --- /dev/null +++ b/src/main/resources/assets/aphelion/lang/en_us.json @@ -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" +} diff --git a/src/main/resources/assets/aphelion/sounds.json b/src/main/resources/assets/aphelion/sounds.json new file mode 100644 index 0000000..c3bebb5 --- /dev/null +++ b/src/main/resources/assets/aphelion/sounds.json @@ -0,0 +1,10 @@ +{ + "bit_shift": { + "sounds": [ + { + "name": "aphelion:bit_shift", + "stream": true + } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/aphelion/sounds/bit_shift.ogg b/src/main/resources/assets/aphelion/sounds/bit_shift.ogg new file mode 100644 index 0000000..ac3e93b Binary files /dev/null and b/src/main/resources/assets/aphelion/sounds/bit_shift.ogg differ diff --git a/src/main/resources/assets/aphelion/textures/block/block_steel.png b/src/main/resources/assets/aphelion/textures/block/block_steel.png new file mode 100644 index 0000000..0d2a750 Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/block/block_steel.png differ diff --git a/src/main/resources/assets/aphelion/textures/block/dimension_changer.png b/src/main/resources/assets/aphelion/textures/block/dimension_changer.png new file mode 100644 index 0000000..58a8d4b Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/block/dimension_changer.png differ diff --git a/src/main/resources/assets/aphelion/textures/block/electric_arc_furnace_front.png b/src/main/resources/assets/aphelion/textures/block/electric_arc_furnace_front.png new file mode 100644 index 0000000..58a8d4b Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/block/electric_arc_furnace_front.png differ diff --git a/src/main/resources/assets/aphelion/textures/block/test_block.png b/src/main/resources/assets/aphelion/textures/block/test_block.png new file mode 100644 index 0000000..58a8d4b Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/block/test_block.png differ diff --git a/src/main/resources/assets/aphelion/textures/gui/base/arrow_progress.png b/src/main/resources/assets/aphelion/textures/gui/base/arrow_progress.png new file mode 100644 index 0000000..a745f74 Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/gui/base/arrow_progress.png differ diff --git a/src/main/resources/assets/aphelion/textures/gui/electric_arc_furnace/gui.png b/src/main/resources/assets/aphelion/textures/gui/electric_arc_furnace/gui.png new file mode 100644 index 0000000..e2cc7fe Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/gui/electric_arc_furnace/gui.png differ diff --git a/src/main/resources/assets/aphelion/textures/gui/test_block/gui.png b/src/main/resources/assets/aphelion/textures/gui/test_block/gui.png new file mode 100644 index 0000000..9f70154 Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/gui/test_block/gui.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_aluminum.png b/src/main/resources/assets/aphelion/textures/item/ingot_aluminum.png new file mode 100644 index 0000000..65936df Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_aluminum.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_cobalt.png b/src/main/resources/assets/aphelion/textures/item/ingot_cobalt.png new file mode 100644 index 0000000..6d818aa Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_cobalt.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_iridium.png b/src/main/resources/assets/aphelion/textures/item/ingot_iridium.png new file mode 100644 index 0000000..119b32e Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_iridium.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_neodymium.png b/src/main/resources/assets/aphelion/textures/item/ingot_neodymium.png new file mode 100644 index 0000000..1c06bee Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_neodymium.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_steel.png b/src/main/resources/assets/aphelion/textures/item/ingot_steel.png new file mode 100644 index 0000000..ef4a76f Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_steel.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_titanium.png b/src/main/resources/assets/aphelion/textures/item/ingot_titanium.png new file mode 100644 index 0000000..9b061c9 Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_titanium.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_tungsten.png b/src/main/resources/assets/aphelion/textures/item/ingot_tungsten.png new file mode 100644 index 0000000..38022f1 Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_tungsten.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/ingot_uranium.png b/src/main/resources/assets/aphelion/textures/item/ingot_uranium.png new file mode 100644 index 0000000..18e217f Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/ingot_uranium.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/music_disc_bit_shift.png b/src/main/resources/assets/aphelion/textures/item/music_disc_bit_shift.png new file mode 100644 index 0000000..d449196 Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/music_disc_bit_shift.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/oil_bucket.png b/src/main/resources/assets/aphelion/textures/item/oil_bucket.png new file mode 100644 index 0000000..2f3c04d Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/oil_bucket.png differ diff --git a/src/main/resources/assets/aphelion/textures/item/test_item.png b/src/main/resources/assets/aphelion/textures/item/test_item.png new file mode 100644 index 0000000..58a8d4b Binary files /dev/null and b/src/main/resources/assets/aphelion/textures/item/test_item.png differ diff --git a/src/main/resources/assets/extreme_rocketry/blockstates/test_block.json b/src/main/resources/assets/extreme_rocketry/blockstates/test_block.json deleted file mode 100644 index 5b5046f..0000000 --- a/src/main/resources/assets/extreme_rocketry/blockstates/test_block.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "extreme_rocketry:block/test_block" - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/extreme_rocketry/lang/en_us.json b/src/main/resources/assets/extreme_rocketry/lang/en_us.json deleted file mode 100644 index b5eb95b..0000000 --- a/src/main/resources/assets/extreme_rocketry/lang/en_us.json +++ /dev/null @@ -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" -} diff --git a/src/main/resources/assets/extreme_rocketry/models/block/test_block.json b/src/main/resources/assets/extreme_rocketry/models/block/test_block.json deleted file mode 100644 index 4b73261..0000000 --- a/src/main/resources/assets/extreme_rocketry/models/block/test_block.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:block/cube_all", - "textures": { - "all": "extreme_rocketry:block/test_block" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/extreme_rocketry/models/item/test_block.json b/src/main/resources/assets/extreme_rocketry/models/item/test_block.json deleted file mode 100644 index 11b3110..0000000 --- a/src/main/resources/assets/extreme_rocketry/models/item/test_block.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "extreme_rocketry:block/test_block" -} \ No newline at end of file diff --git a/src/main/resources/assets/extreme_rocketry/models/item/test_item.json b/src/main/resources/assets/extreme_rocketry/models/item/test_item.json deleted file mode 100644 index 2f3a635..0000000 --- a/src/main/resources/assets/extreme_rocketry/models/item/test_item.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "extreme_rocketry:item/test_item" - } -} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/dimension/space.json b/src/main/resources/data/aphelion/dimension/space.json new file mode 100644 index 0000000..9580d90 --- /dev/null +++ b/src/main/resources/data/aphelion/dimension/space.json @@ -0,0 +1,11 @@ +{ + "type": "aphelion:space", + "generator": { + "type": "minecraft:noise", + "biome_source": { + "type": "minecraft:fixed", + "biome": "aphelion:space" + }, + "settings": "aphelion:space" + } +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/dimension/test.json b/src/main/resources/data/aphelion/dimension/test.json new file mode 100644 index 0000000..fa45db2 --- /dev/null +++ b/src/main/resources/data/aphelion/dimension/test.json @@ -0,0 +1,11 @@ +{ + "type": "aphelion:test", + "generator": { + "type": "minecraft:noise", + "biome_source": { + "type": "minecraft:fixed", + "biome": "aphelion:test" + }, + "settings": "aphelion:test" + } +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/dimension_type/space.json b/src/main/resources/data/aphelion/dimension_type/space.json new file mode 100644 index 0000000..e6b1186 --- /dev/null +++ b/src/main/resources/data/aphelion/dimension_type/space.json @@ -0,0 +1,23 @@ +{ + "ambient_light": 0, + "bed_works": false, + "coordinate_scale": 1, + "effects": "aphelion:space", + "has_ceiling": false, + "has_raids": true, + "has_skylight": true, + "height": 256, + "infiniburn": "#minecraft:infiniburn_overworld", + "logical_height": 256, + "min_y": -64, + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": { + "type": "minecraft:uniform", + "max_inclusive": 7, + "min_inclusive": 0 + }, + "natural": false, + "piglin_safe": false, + "respawn_anchor_works": true, + "ultrawarm": false +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/dimension_type/test.json b/src/main/resources/data/aphelion/dimension_type/test.json new file mode 100644 index 0000000..5046dfa --- /dev/null +++ b/src/main/resources/data/aphelion/dimension_type/test.json @@ -0,0 +1,23 @@ +{ + "ambient_light": 0, + "bed_works": false, + "coordinate_scale": 1, + "has_ceiling": false, + "has_raids": true, + "has_skylight": true, + "height": 256, + "effects": "aphelion:test", + "infiniburn": "#minecraft:infiniburn_overworld", + "logical_height": 256, + "min_y": 0, + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": { + "type": "minecraft:uniform", + "max_inclusive": 7, + "min_inclusive": 0 + }, + "natural": false, + "piglin_safe": false, + "respawn_anchor_works": true, + "ultrawarm": false +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/jukebox_song/bit_shift.json b/src/main/resources/data/aphelion/jukebox_song/bit_shift.json new file mode 100644 index 0000000..b8d9a29 --- /dev/null +++ b/src/main/resources/data/aphelion/jukebox_song/bit_shift.json @@ -0,0 +1,8 @@ +{ + "comparator_output": 15, + "description": { + "translate": "item.aphelion.music_disc_bit_shift.desc" + }, + "length_in_seconds": 123.7, + "sound_event": "aphelion:bit_shift" +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/worldgen/biome/space.json b/src/main/resources/data/aphelion/worldgen/biome/space.json new file mode 100644 index 0000000..60fe03e --- /dev/null +++ b/src/main/resources/data/aphelion/worldgen/biome/space.json @@ -0,0 +1,30 @@ +{ + "carvers": {}, + "downfall": 0.0, + "effects": { + "fog_color": 12638463, + "mood_sound": { + "block_search_extent": 8, + "offset": 2.0, + "sound": "minecraft:ambient.cave", + "tick_delay": 6000 + }, + "sky_color": 7907327, + "water_color": 4159204, + "water_fog_color": 329011 + }, + "features": [], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 0.5 +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/worldgen/biome/test.json b/src/main/resources/data/aphelion/worldgen/biome/test.json new file mode 100644 index 0000000..7d1be05 --- /dev/null +++ b/src/main/resources/data/aphelion/worldgen/biome/test.json @@ -0,0 +1,30 @@ +{ + "carvers": {}, + "downfall": 0, + "effects": { + "fog_color": 12638463, + "mood_sound": { + "block_search_extent": 8, + "offset": 2, + "sound": "minecraft:ambient.cave", + "tick_delay": 6000 + }, + "sky_color": 3079224, + "water_color": 4159204, + "water_fog_color": 329011 + }, + "features": [], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 0.5 +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/worldgen/noise_settings/space.json b/src/main/resources/data/aphelion/worldgen/noise_settings/space.json new file mode 100644 index 0000000..6fa8e17 --- /dev/null +++ b/src/main/resources/data/aphelion/worldgen/noise_settings/space.json @@ -0,0 +1,43 @@ +{ + "aquifers_enabled": false, + "default_block": { + "Name": "minecraft:air" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": true, + "legacy_random_source": false, + "noise": { + "height": 256, + "min_y": 0, + "size_horizontal": 2, + "size_vertical": 1 + }, + "noise_router": { + "barrier": 0, + "continents": 0, + "depth": 0, + "erosion": 0, + "final_density": 0, + "fluid_level_floodedness": 0, + "fluid_level_spread": 0, + "initial_density_without_jaggedness": 0, + "lava": 0, + "ridges": 0, + "temperature": 0, + "vegetation": 0, + "vein_gap": 0, + "vein_ridged": 0, + "vein_toggle": 0 + }, + "ore_veins_enabled": false, + "sea_level": 0, + "spawn_target": [], + "surface_rule": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:air" + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/aphelion/worldgen/noise_settings/test.json b/src/main/resources/data/aphelion/worldgen/noise_settings/test.json new file mode 100644 index 0000000..6fa8e17 --- /dev/null +++ b/src/main/resources/data/aphelion/worldgen/noise_settings/test.json @@ -0,0 +1,43 @@ +{ + "aquifers_enabled": false, + "default_block": { + "Name": "minecraft:air" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": true, + "legacy_random_source": false, + "noise": { + "height": 256, + "min_y": 0, + "size_horizontal": 2, + "size_vertical": 1 + }, + "noise_router": { + "barrier": 0, + "continents": 0, + "depth": 0, + "erosion": 0, + "final_density": 0, + "fluid_level_floodedness": 0, + "fluid_level_spread": 0, + "initial_density_without_jaggedness": 0, + "lava": 0, + "ridges": 0, + "temperature": 0, + "vegetation": 0, + "vein_gap": 0, + "vein_ridged": 0, + "vein_toggle": 0 + }, + "ore_veins_enabled": false, + "sea_level": 0, + "spawn_target": [], + "surface_rule": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:air" + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/dimension/space.json b/src/main/resources/data/data/aphelion/dimension/space.json new file mode 100644 index 0000000..fa45db2 --- /dev/null +++ b/src/main/resources/data/data/aphelion/dimension/space.json @@ -0,0 +1,11 @@ +{ + "type": "aphelion:test", + "generator": { + "type": "minecraft:noise", + "biome_source": { + "type": "minecraft:fixed", + "biome": "aphelion:test" + }, + "settings": "aphelion:test" + } +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/dimension/test.json b/src/main/resources/data/data/aphelion/dimension/test.json new file mode 100644 index 0000000..fa45db2 --- /dev/null +++ b/src/main/resources/data/data/aphelion/dimension/test.json @@ -0,0 +1,11 @@ +{ + "type": "aphelion:test", + "generator": { + "type": "minecraft:noise", + "biome_source": { + "type": "minecraft:fixed", + "biome": "aphelion:test" + }, + "settings": "aphelion:test" + } +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/dimension_type/space.json b/src/main/resources/data/data/aphelion/dimension_type/space.json new file mode 100644 index 0000000..5046dfa --- /dev/null +++ b/src/main/resources/data/data/aphelion/dimension_type/space.json @@ -0,0 +1,23 @@ +{ + "ambient_light": 0, + "bed_works": false, + "coordinate_scale": 1, + "has_ceiling": false, + "has_raids": true, + "has_skylight": true, + "height": 256, + "effects": "aphelion:test", + "infiniburn": "#minecraft:infiniburn_overworld", + "logical_height": 256, + "min_y": 0, + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": { + "type": "minecraft:uniform", + "max_inclusive": 7, + "min_inclusive": 0 + }, + "natural": false, + "piglin_safe": false, + "respawn_anchor_works": true, + "ultrawarm": false +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/dimension_type/test.json b/src/main/resources/data/data/aphelion/dimension_type/test.json new file mode 100644 index 0000000..5046dfa --- /dev/null +++ b/src/main/resources/data/data/aphelion/dimension_type/test.json @@ -0,0 +1,23 @@ +{ + "ambient_light": 0, + "bed_works": false, + "coordinate_scale": 1, + "has_ceiling": false, + "has_raids": true, + "has_skylight": true, + "height": 256, + "effects": "aphelion:test", + "infiniburn": "#minecraft:infiniburn_overworld", + "logical_height": 256, + "min_y": 0, + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": { + "type": "minecraft:uniform", + "max_inclusive": 7, + "min_inclusive": 0 + }, + "natural": false, + "piglin_safe": false, + "respawn_anchor_works": true, + "ultrawarm": false +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/worldgen/biome/space.json b/src/main/resources/data/data/aphelion/worldgen/biome/space.json new file mode 100644 index 0000000..60fe03e --- /dev/null +++ b/src/main/resources/data/data/aphelion/worldgen/biome/space.json @@ -0,0 +1,30 @@ +{ + "carvers": {}, + "downfall": 0.0, + "effects": { + "fog_color": 12638463, + "mood_sound": { + "block_search_extent": 8, + "offset": 2.0, + "sound": "minecraft:ambient.cave", + "tick_delay": 6000 + }, + "sky_color": 7907327, + "water_color": 4159204, + "water_fog_color": 329011 + }, + "features": [], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 0.5 +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/worldgen/biome/test.json b/src/main/resources/data/data/aphelion/worldgen/biome/test.json new file mode 100644 index 0000000..7d1be05 --- /dev/null +++ b/src/main/resources/data/data/aphelion/worldgen/biome/test.json @@ -0,0 +1,30 @@ +{ + "carvers": {}, + "downfall": 0, + "effects": { + "fog_color": 12638463, + "mood_sound": { + "block_search_extent": 8, + "offset": 2, + "sound": "minecraft:ambient.cave", + "tick_delay": 6000 + }, + "sky_color": 3079224, + "water_color": 4159204, + "water_fog_color": 329011 + }, + "features": [], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 0.5 +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/worldgen/noise_settings/space.json b/src/main/resources/data/data/aphelion/worldgen/noise_settings/space.json new file mode 100644 index 0000000..6fa8e17 --- /dev/null +++ b/src/main/resources/data/data/aphelion/worldgen/noise_settings/space.json @@ -0,0 +1,43 @@ +{ + "aquifers_enabled": false, + "default_block": { + "Name": "minecraft:air" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": true, + "legacy_random_source": false, + "noise": { + "height": 256, + "min_y": 0, + "size_horizontal": 2, + "size_vertical": 1 + }, + "noise_router": { + "barrier": 0, + "continents": 0, + "depth": 0, + "erosion": 0, + "final_density": 0, + "fluid_level_floodedness": 0, + "fluid_level_spread": 0, + "initial_density_without_jaggedness": 0, + "lava": 0, + "ridges": 0, + "temperature": 0, + "vegetation": 0, + "vein_gap": 0, + "vein_ridged": 0, + "vein_toggle": 0 + }, + "ore_veins_enabled": false, + "sea_level": 0, + "spawn_target": [], + "surface_rule": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:air" + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/data/aphelion/worldgen/noise_settings/test.json b/src/main/resources/data/data/aphelion/worldgen/noise_settings/test.json new file mode 100644 index 0000000..6fa8e17 --- /dev/null +++ b/src/main/resources/data/data/aphelion/worldgen/noise_settings/test.json @@ -0,0 +1,43 @@ +{ + "aquifers_enabled": false, + "default_block": { + "Name": "minecraft:air" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": true, + "legacy_random_source": false, + "noise": { + "height": 256, + "min_y": 0, + "size_horizontal": 2, + "size_vertical": 1 + }, + "noise_router": { + "barrier": 0, + "continents": 0, + "depth": 0, + "erosion": 0, + "final_density": 0, + "fluid_level_floodedness": 0, + "fluid_level_spread": 0, + "initial_density_without_jaggedness": 0, + "lava": 0, + "ridges": 0, + "temperature": 0, + "vegetation": 0, + "vein_gap": 0, + "vein_ridged": 0, + "vein_toggle": 0 + }, + "ore_veins_enabled": false, + "sea_level": 0, + "spawn_target": [], + "surface_rule": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:air" + } + } +} \ No newline at end of file diff --git a/src/main/resources/space.json b/src/main/resources/space.json new file mode 100644 index 0000000..87ce764 --- /dev/null +++ b/src/main/resources/space.json @@ -0,0 +1,14 @@ +{ + "custom_clouds": false, + "custom_sky": true, + "custom_weather": false, + "dimension": "aphelion:space", + "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 +} \ No newline at end of file