diff --git a/Common/src/main/java/com/hypherionmc/craterlib/core/network/CraterNetworkHandler.java b/Common/src/main/java/com/hypherionmc/craterlib/core/network/CraterNetworkHandler.java index eb34a06..cb32346 100644 --- a/Common/src/main/java/com/hypherionmc/craterlib/core/network/CraterNetworkHandler.java +++ b/Common/src/main/java/com/hypherionmc/craterlib/core/network/CraterNetworkHandler.java @@ -12,7 +12,7 @@ import java.util.function.Supplier; */ public interface CraterNetworkHandler { - > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection); + > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection); Packet toServerBound(CraterPacket packet); diff --git a/Fabric/src/main/java/com/hypherionmc/craterlib/network/FabricNetworkHandler.java b/Fabric/src/main/java/com/hypherionmc/craterlib/network/FabricNetworkHandler.java index 76e5224..d20f26e 100644 --- a/Fabric/src/main/java/com/hypherionmc/craterlib/network/FabricNetworkHandler.java +++ b/Fabric/src/main/java/com/hypherionmc/craterlib/network/FabricNetworkHandler.java @@ -36,7 +36,7 @@ public class FabricNetworkHandler implements CraterNetworkHandler { } @Override - public > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection) { + public > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection) { ResourceLocation channelName = this.nextId(); this.packets.put(clazz, new PacketData(clazz, channelName, packetDirection)); diff --git a/Forge/build.gradle b/Forge/build.gradle index d441d08..4c3566a 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -107,7 +107,7 @@ publisher { curseID = curse_id modrinthID = modrinth_id versionType = "release" - changelog = rootProject.file("changelog-fabric.md") + changelog = rootProject.file("changelog-forge.md") version = "${minecraft_version}-${project.version}" displayName = "[FORGE 1.20.2] CraterLib - ${project.version}" gameVersions = ["1.20.2"] diff --git a/Forge/src/main/java/com/hypherionmc/craterlib/network/ForgeNetworkHandler.java b/Forge/src/main/java/com/hypherionmc/craterlib/network/ForgeNetworkHandler.java index 6eb4d69..7d97684 100644 --- a/Forge/src/main/java/com/hypherionmc/craterlib/network/ForgeNetworkHandler.java +++ b/Forge/src/main/java/com/hypherionmc/craterlib/network/ForgeNetworkHandler.java @@ -51,7 +51,7 @@ public class ForgeNetworkHandler implements CraterNetworkHandler { } @Override - public > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection) { + public > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection) { BiConsumer encoder = CraterPacket::write; Function decoder = buf -> { T packet = supplier.get(); diff --git a/Forge/src/main/resources/META-INF/mods.toml b/Forge/src/main/resources/META-INF/mods.toml index 8189f0f..391ac05 100644 --- a/Forge/src/main/resources/META-INF/mods.toml +++ b/Forge/src/main/resources/META-INF/mods.toml @@ -26,6 +26,6 @@ side = "BOTH" [[dependencies.${mod_id}]] modId = "minecraft" mandatory = true -versionRange = "[1.20,)" +versionRange = "[1.20.2,1.21)" ordering = "NONE" side = "BOTH" diff --git a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform index a12ad8c..5bd719f 100644 --- a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform +++ b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform @@ -1 +1 @@ -com.hypherionmc.craterlib.client.ForgeClientHelper \ No newline at end of file +com.hypherionmc.craterlib.client.NeoForgeClientHelper \ No newline at end of file diff --git a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform index 09e119f..6cb6efb 100644 --- a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform +++ b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform @@ -1 +1 @@ -com.hypherionmc.craterlib.common.ForgeCommonHelper \ No newline at end of file +com.hypherionmc.craterlib.common.NeoForgeCommonHelper \ No newline at end of file diff --git a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper index ad50794..7c023ac 100644 --- a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper +++ b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper @@ -1 +1 @@ -com.hypherionmc.craterlib.common.ForgeFluidHelper \ No newline at end of file +com.hypherionmc.craterlib.common.NeoForgeFluidHelper \ No newline at end of file diff --git a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment index 02b4e07..9a41f05 100644 --- a/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment +++ b/Forge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment @@ -1 +1 @@ -com.hypherionmc.craterlib.common.ForgeLoaderHelper \ No newline at end of file +com.hypherionmc.craterlib.common.NeoForgeLoaderHelper \ No newline at end of file diff --git a/NeoForge/build.gradle b/NeoForge/build.gradle new file mode 100644 index 0000000..341527b --- /dev/null +++ b/NeoForge/build.gradle @@ -0,0 +1,119 @@ +// Adjust the output jar name here +archivesBaseName = "${mod_name.replace(" ", "")}-NeoForge-${minecraft_version}" + +dependencies { + shade "me.hypherionmc.moon-config:core:${moon_config}" + shade "me.hypherionmc.moon-config:toml:${moon_config}" + shade "com.hypherionmc:rpcsdk:1.0" + + // Do not edit or remove + implementation project(":Common") +} + +shadowJar { + from sourceSets.main.output + configurations = [project.configurations.shade] + + dependencies { + relocate 'me.hypherionmc.moonconfig', 'shadow.hypherionmc.moonconfig' + } + + setArchiveClassifier('dev-shadow') +} + +/** + * =============================================================================== + * = DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING = + * =============================================================================== + */ + +unimined.minecraft { + neoForged { + loader neoforge_version + mixinConfig("${mod_id}.mixins.json", "${mod_id}.neoforge.mixins.json") + } +} + +remapJar { + inputFile.set shadowJar.archiveFile + dependsOn shadowJar + archiveClassifier.set null +} + +jar { + archiveClassifier.set "dev" +} + +processResources { + from project(":Common").sourceSets.main.resources + def buildProps = project.properties.clone() + + filesMatching("META-INF/mods.toml") { + expand buildProps + } +} + +compileTestJava.enabled = false + +tasks.withType(JavaCompile).configureEach { + source(project(":Common").sourceSets.main.allSource) +} + +/** + * Publishing Config + */ +publishing { + publications { + mavenJava(MavenPublication) { + groupId project.group + artifactId project.archivesBaseName + version project.version + from components.java + + artifact(remapJar) { + builtBy remapJar + } + + pom.withXml { + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + it.artifactId.text() == 'regutils-joined-fabric' || + it.artifactId.text() == 'core' || + it.artifactId.text() == 'toml' + }.each() { + it.parent().remove(it) + } + } + } + } + + repositories { + maven { + url "https://maven.firstdark.dev/" + (project.release ? "releases" : "snapshots") + credentials { + username System.getenv("MAVEN_USER") + password System.getenv("MAVEN_PASS") + } + } + } +} + +publisher { + apiKeys { + modrinth = System.getenv("MODRINTH_TOKEN") + curseforge = System.getenv("CURSE_TOKEN") + } + + curseID = curse_id + modrinthID = modrinth_id + versionType = "release" + changelog = rootProject.file("changelog-forge.md") + version = "${minecraft_version}-${project.version}" + displayName = "[NEOFORGE 1.20.2] CraterLib - ${project.version}" + gameVersions = ["1.20.2"] + loaders = ["neoforge"] + artifact = remapJar +} + +publishCurseforge.dependsOn(remapJar) +publishModrinth.dependsOn(remapJar) \ No newline at end of file diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/CraterLib.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/CraterLib.java new file mode 100644 index 0000000..0f91943 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/CraterLib.java @@ -0,0 +1,30 @@ +package com.hypherionmc.craterlib; + +import com.hypherionmc.craterlib.api.event.client.LateInitEvent; +import com.hypherionmc.craterlib.client.CraterClientBus; +import com.hypherionmc.craterlib.common.NeoForgeServerEvents; +import com.hypherionmc.craterlib.core.event.CraterEventBus; +import net.minecraft.client.Minecraft; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.common.NeoForge; + +@Mod(CraterConstants.MOD_ID) +public class CraterLib { + + public CraterLib(IEventBus eventBus) { + CraterEventBus.INSTANCE.registerEventListener(CraterClientBus.class); + NeoForge.EVENT_BUS.register(new NeoForgeServerEvents()); + FMLJavaModLoadingContext.get().getModEventBus().addListener(this::commonSetup); + } + + public void commonSetup(FMLCommonSetupEvent evt) { + if (FMLEnvironment.dist.isClient()) { + LateInitEvent event = new LateInitEvent(Minecraft.getInstance(), Minecraft.getInstance().options); + CraterEventBus.INSTANCE.postEvent(event); + } + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/client/CraterClientBus.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/CraterClientBus.java new file mode 100644 index 0000000..9cf2f00 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/CraterClientBus.java @@ -0,0 +1,32 @@ +package com.hypherionmc.craterlib.client; + +import com.hypherionmc.craterlib.CraterConstants; +import com.hypherionmc.craterlib.api.event.client.LateInitEvent; +import com.hypherionmc.craterlib.core.event.annot.CraterEventListener; +import com.hypherionmc.craterlib.core.systems.internal.CreativeTabRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.CreativeModeTab; + +public class CraterClientBus { + + @CraterEventListener + public static void lateInit(LateInitEvent event) { + CraterConstants.LOG.info("Registering Creative Tabs"); + + CreativeTabRegistry.getTabs().forEach(tab -> { + CreativeModeTab.Builder builder = CreativeModeTab.builder(); + builder.title(Component.translatable("itemGroup." + tab.getResourceLocation().toString().replace(":", "."))); + builder.icon(tab.getIcon()); + + if (!tab.getBackgroundSuffix().isEmpty()) { + builder.backgroundSuffix(tab.getBackgroundSuffix()); + } + + CreativeModeTab tabb = Registry.register(BuiltInRegistries.CREATIVE_MODE_TAB, tab.getResourceKey(), builder.build()); + tab.setTab(tabb); + }); + } + +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/client/NeoForgeClientEvents.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/NeoForgeClientEvents.java new file mode 100644 index 0000000..fe47f52 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/NeoForgeClientEvents.java @@ -0,0 +1,21 @@ +package com.hypherionmc.craterlib.client; + +import com.hypherionmc.craterlib.CraterConstants; +import com.hypherionmc.craterlib.api.event.client.CraterClientTickEvent; +import com.hypherionmc.craterlib.core.event.CraterEventBus; +import net.minecraft.client.Minecraft; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.event.TickEvent; + +@Mod.EventBusSubscriber(modid = CraterConstants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT) +public class NeoForgeClientEvents { + + @SubscribeEvent + public static void clientTick(TickEvent.LevelTickEvent event) { + CraterClientTickEvent craterClientTickEvent = new CraterClientTickEvent(Minecraft.getInstance().level); + CraterEventBus.INSTANCE.postEvent(craterClientTickEvent); + } + +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/client/NeoForgeClientHelper.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/NeoForgeClientHelper.java new file mode 100644 index 0000000..914a7d6 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/NeoForgeClientHelper.java @@ -0,0 +1,69 @@ +package com.hypherionmc.craterlib.client; + +import com.hypherionmc.craterlib.common.item.BlockItemDyable; +import com.hypherionmc.craterlib.core.platform.ClientPlatform; +import com.hypherionmc.craterlib.util.ColorPropertyFunction; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; +import net.minecraft.client.renderer.item.ItemProperties; +import net.minecraft.network.Connection; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.neoforged.fml.loading.FMLEnvironment; + +import java.util.Objects; + +/** + * @author HypherionSA + * @date 16/06/2022 + */ +public class NeoForgeClientHelper implements ClientPlatform { + + public NeoForgeClientHelper() {} + + @Override + public void registerItemProperty(BlockItemDyable item, String property) { + if (FMLEnvironment.dist.isClient()) { + ItemProperties.register(item, new ResourceLocation(property), new ColorPropertyFunction(item)); + } + } + + /*@Override + public void registerCustomRenderTypes(Collection> blocks) { + blocks.forEach(blk -> { + if (blk.get() instanceof CustomRenderType type) { + ItemBlockRenderTypes.setRenderLayer(blk.get(), type.getCustomRenderType()); + } + }); + }*/ + + @Override + public Minecraft getClientInstance() { + return Minecraft.getInstance(); + } + + @Override + public Player getClientPlayer() { + return Minecraft.getInstance().player; + } + + @Override + public Level getClientLevel() { + return Minecraft.getInstance().level; + } + + @Override + public Connection getClientConnection() { + Objects.requireNonNull(Minecraft.getInstance().getConnection(), "Cannot send packets when not in game!"); + return Minecraft.getInstance().getConnection().getConnection(); + } + + @Override + public void registerBlockEntityRenderer(BlockEntityType blockEntityType, BlockEntityRendererProvider blockEntityRendererFactory) { + BlockEntityRenderers.register(blockEntityType, blockEntityRendererFactory); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/client/gui/widgets/FluidStackWidget.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/gui/widgets/FluidStackWidget.java new file mode 100644 index 0000000..f8c9ed0 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/client/gui/widgets/FluidStackWidget.java @@ -0,0 +1,101 @@ +package com.hypherionmc.craterlib.client.gui.widgets; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.texture.AbstractTexture; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FastColor; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.templates.FluidTank; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +/** Copied from ...*/ +public class FluidStackWidget extends AbstractWidget { + + private final Screen displayOn; + private final Supplier getFluid; + + private final String toolTipTitle; + + public FluidStackWidget(Screen displayOn, Supplier getFluid, int pX, int pY, int pWidth, int pHeight, String toolTipTitle) { + super(pX, pY, pWidth, pHeight, Component.empty()); + this.displayOn = displayOn; + this.getFluid = getFluid; + this.toolTipTitle = toolTipTitle; + } + + @Override + public void renderWidget(@NotNull GuiGraphics pPoseStack, int pMouseX, int pMouseY, float pPartialTicks) { + Minecraft minecraft = Minecraft.getInstance(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.defaultBlendFunc(); + RenderSystem.enableDepthTest(); + FluidTank fluidTank = getFluid.get(); + if (!fluidTank.isEmpty()) { + FluidStack fluidStack = fluidTank.getFluid(); + IClientFluidTypeExtensions props = IClientFluidTypeExtensions.of(fluidStack.getFluid()); + ResourceLocation still = props.getStillTexture(fluidStack); + if (still != null) { + AbstractTexture texture = minecraft.getTextureManager().getTexture(TextureAtlas.LOCATION_BLOCKS); + if (texture instanceof TextureAtlas atlas) { + TextureAtlasSprite sprite = atlas.getSprite(still); + RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_BLOCKS); + + int color = props.getTintColor(); + RenderSystem.setShaderColor( + FastColor.ARGB32.red(color) / 255.0F, + FastColor.ARGB32.green(color) / 255.0F, + FastColor.ARGB32.blue(color) / 255.0F, + FastColor.ARGB32.alpha(color) / 255.0F); + RenderSystem.enableBlend(); + + int stored = fluidTank.getFluidAmount(); + float capacity = fluidTank.getCapacity(); + float filledVolume = stored / capacity; + int renderableHeight = (int)(filledVolume * height); + + int atlasWidth = (int)(sprite.getY() / (sprite.getU1() - sprite.getU0())); + int atlasHeight = (int)(sprite.getY() / (sprite.getV1() - sprite.getV0())); + + pPoseStack.pose().pushPose(); + pPoseStack.pose().translate(0, height-16, 0); + for (int i = 0; i < Math.ceil(renderableHeight / 16f); i++) { + int drawingHeight = Math.min(16, renderableHeight - 16*i); + int notDrawingHeight = 16 - drawingHeight; + // TODO Double Check this + pPoseStack.blit(TextureAtlas.LOCATION_BLOCKS, getX(), getY() + notDrawingHeight, 0, sprite.getU0()*atlasWidth, sprite.getV0()*atlasHeight + notDrawingHeight, this.width, drawingHeight, atlasWidth, atlasHeight); + pPoseStack.pose().translate(0,-16, 0); + } + + RenderSystem.setShaderColor(1, 1, 1, 1); + pPoseStack.pose().popPose(); + } + } + //renderToolTip(pPoseStack, pMouseX, pMouseY); + } + } + + @Override + protected void updateWidgetNarration(NarrationElementOutput p_259858_) { + + } + + // TODO Fix Tooltips + /*@Override + public void renderToolTip(PoseStack pPoseStack, int pMouseX, int pMouseY) { + if (isActive() && isHovered) { + displayOn.renderTooltip(pPoseStack, Arrays.asList(LangUtils.getTooltipTitle(toolTipTitle).getVisualOrderText(), Component.literal((int) (((float)this.getFluid.get().getFluidAmount() / this.getFluid.get().getCapacity()) * 100) + "%").getVisualOrderText()), pMouseX, pMouseY); + } + }*/ +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeCommonEvents.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeCommonEvents.java new file mode 100644 index 0000000..c62bad5 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeCommonEvents.java @@ -0,0 +1,21 @@ +package com.hypherionmc.craterlib.common; + +import com.hypherionmc.craterlib.CraterConstants; +import com.hypherionmc.craterlib.core.systems.internal.CreativeTabRegistry; +import net.minecraft.world.item.CreativeModeTab; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; + +@Mod.EventBusSubscriber(modid = CraterConstants.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class NeoForgeCommonEvents { + + @SubscribeEvent + public static void registerTabs(BuildCreativeModeTabContentsEvent event) { + CreativeModeTab tab = event.getTab(); + + CreativeTabRegistry.getTabItems().stream() + .filter(p -> p.getLeft().get() == tab && p.getRight() != null) + .forEach(itemPair -> event.accept(itemPair.getRight().get())); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeCommonHelper.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeCommonHelper.java new file mode 100644 index 0000000..71c3b3e --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeCommonHelper.java @@ -0,0 +1,90 @@ +package com.hypherionmc.craterlib.common; + +import com.hypherionmc.craterlib.api.blockentity.caps.CraterCapabilityHandler; +import com.hypherionmc.craterlib.api.blockentity.caps.ICraterCapProvider; +import com.hypherionmc.craterlib.core.network.CraterNetworkHandler; +import com.hypherionmc.craterlib.core.platform.CommonPlatform; +import com.hypherionmc.craterlib.core.systems.fluid.ICraterFluidHandler; +import com.hypherionmc.craterlib.network.NeoForgeNetworkHandler; +import com.hypherionmc.craterlib.systems.energy.NeoForgeEnergyReader; +import com.hypherionmc.craterlib.systems.fluid.NeoForgeFluidReader; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.neoforged.neoforge.common.capabilities.Capabilities; +import net.neoforged.neoforge.common.extensions.IMenuTypeExtension; +import net.neoforged.neoforge.server.ServerLifecycleHooks; +import org.apache.commons.lang3.function.TriFunction; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +/** + * @author HypherionSA + */ +public class NeoForgeCommonHelper implements CommonPlatform { + + public static Map TABS = new HashMap<>(); + + public NeoForgeCommonHelper() {} + + @Override + public CraterNetworkHandler createPacketHandler(String modid, boolean requiredClient, boolean requiredServer) { + return NeoForgeNetworkHandler.of(modid, requiredClient, requiredServer); + } + + @Override + public MinecraftServer getMCServer() { + return ServerLifecycleHooks.getCurrentServer(); + } + + @Override + public void openMenu(ServerPlayer player, MenuProvider menu, @Nullable Consumer initialData) { + // TODO Fix Menus + /*if (initialData != null) { + player.openMenu(menu, initialData); + } else { + player.openMenu(menu, player.getOnPos()); + }*/ + } + + @Override + public MenuType createMenuType(TriFunction constructor) { + return IMenuTypeExtension.create(constructor::apply); + } + + @Override + public Optional getCapabilityHandler(BlockEntity entity, Direction side, CraterCapabilityHandler capability) { + if (capability == CraterCapabilityHandler.ENERGY) { + AtomicReference energyReference = new AtomicReference<>(); + entity.getCapability(Capabilities.ENERGY, side).ifPresent(storage -> energyReference.set(new NeoForgeEnergyReader(storage))); + + return energyReference.get() != null ? (Optional) Optional.of(energyReference.get()) : Optional.empty(); + } + + if (capability == CraterCapabilityHandler.FLUID) { + AtomicReference craterFluidHandler = new AtomicReference<>(); + entity.getCapability(Capabilities.FLUID_HANDLER, side).ifPresent(iFluidHandler -> craterFluidHandler.set(new NeoForgeFluidReader(iFluidHandler))); + + return craterFluidHandler.get() != null ? (Optional) Optional.of(craterFluidHandler.get()) : Optional.empty(); + } + + if (entity instanceof ICraterCapProvider capProvider) { + return capProvider.getCapability(capability, side); + } + + return Optional.empty(); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeFluidHelper.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeFluidHelper.java new file mode 100644 index 0000000..0558607 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeFluidHelper.java @@ -0,0 +1,58 @@ +package com.hypherionmc.craterlib.common; + +import com.hypherionmc.craterlib.core.platform.CraterFluidHelper; +import com.hypherionmc.craterlib.core.systems.fluid.CraterFluidTank; +import com.hypherionmc.craterlib.core.systems.fluid.FluidHolder; +import com.hypherionmc.craterlib.core.systems.fluid.ICraterFluidHandler; +import com.hypherionmc.craterlib.systems.fluid.NeoForgeFluidTankInteractor; +import com.hypherionmc.craterlib.systems.fluid.NeoForgeFluidUtils; +import com.hypherionmc.craterlib.systems.fluid.NeoForgeWrappedFluidTank; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +public class NeoForgeFluidHelper implements CraterFluidHelper { + + @Override + public CraterFluidTank createFluidTank(int capacity) { + return new NeoForgeWrappedFluidTank(capacity); + } + + @Override + public CraterFluidTank createFluidTank(int capacity, Fluid... validFluids) { + return new NeoForgeWrappedFluidTank(capacity, (variant) -> Arrays.stream(validFluids).allMatch(f -> f.isSame(variant.getFluid()))); + } + + @Override + public boolean interactWithFluidHandler(Player player, InteractionHand hand, ICraterFluidHandler fluidHandler) { + NeoForgeFluidTankInteractor interactor = new NeoForgeFluidTankInteractor(fluidHandler); + return FluidUtil.interactWithFluidHandler(player, hand, interactor); + } + + @Override + public boolean interactWithFluidHandler(@NotNull Player player, @NotNull InteractionHand hand, @NotNull Level level, @NotNull BlockPos pos, @Nullable Direction side) { + return FluidUtil.interactWithFluidHandler(player, hand, level, pos, side); + } + + @Override + public TextureAtlasSprite getFluidTexture(FluidHolder fluidHolder) { + return NeoForgeFluidUtils.getFluidTexture(new FluidStack(fluidHolder.getFluid(), 0), true); + } + + @Override + public int getFluidColor(Fluid fluid) { + IClientFluidTypeExtensions props = IClientFluidTypeExtensions.of(fluid); + return props.getTintColor(); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeLoaderHelper.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeLoaderHelper.java new file mode 100644 index 0000000..443c127 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeLoaderHelper.java @@ -0,0 +1,72 @@ +package com.hypherionmc.craterlib.common; + +import com.hypherionmc.craterlib.core.platform.Environment; +import com.hypherionmc.craterlib.core.platform.ModloaderEnvironment; +import net.minecraft.SharedConstants; +import net.minecraft.client.Minecraft; +import net.neoforged.fml.ModList; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.FMLPaths; + +import java.io.File; + +/** + * @author HypherionSA + */ +public class NeoForgeLoaderHelper implements ModloaderEnvironment { + + public NeoForgeLoaderHelper() {} + + @Override + public boolean isFabric() { + return false; + } + + @Override + public String getGameVersion() { + return SharedConstants.VERSION_STRING; + } + + @Override + public File getGameFolder() { + return Minecraft.getInstance().gameDirectory; + } + + @Override + public File getConfigFolder() { + return FMLPaths.CONFIGDIR.get().toFile(); + } + + @Override + public File getModsFolder() { + return FMLPaths.MODSDIR.get().toFile(); + } + + @Override + public Environment getEnvironment() { + switch (FMLLoader.getDist()) { + case CLIENT -> { + return Environment.CLIENT; + } + case DEDICATED_SERVER -> { + return Environment.SERVER; + } + } + return Environment.UNKNOWN; + } + + @Override + public boolean isModLoaded(String modid) { + return ModList.get().isLoaded(modid); + } + + @Override + public boolean isDevEnv() { + return !FMLLoader.isProduction(); + } + + @Override + public int getModCount() { + return ModList.get().size(); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeServerEvents.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeServerEvents.java new file mode 100644 index 0000000..8439a05 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/common/NeoForgeServerEvents.java @@ -0,0 +1,40 @@ +package com.hypherionmc.craterlib.common; + +import com.hypherionmc.craterlib.api.event.server.CraterRegisterCommandEvent; +import com.hypherionmc.craterlib.api.event.server.CraterServerLifecycleEvent; +import com.hypherionmc.craterlib.core.event.CraterEventBus; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppedEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; + +public class NeoForgeServerEvents { + + @SubscribeEvent + public void serverStarting(ServerStartingEvent event) { + CraterEventBus.INSTANCE.postEvent(new CraterServerLifecycleEvent.Starting(event.getServer())); + } + + @SubscribeEvent + public void serverStarted(ServerStartedEvent event) { + CraterEventBus.INSTANCE.postEvent(new CraterServerLifecycleEvent.Started()); + } + + @SubscribeEvent + public void serverStopping(ServerStoppingEvent event) { + CraterEventBus.INSTANCE.postEvent(new CraterServerLifecycleEvent.Stopping()); + } + + @SubscribeEvent + public void serverStopped(ServerStoppedEvent event) { + CraterEventBus.INSTANCE.postEvent(new CraterServerLifecycleEvent.Stopped()); + } + + @SubscribeEvent + public void onCommandRegister(RegisterCommandsEvent event) { + CraterEventBus.INSTANCE.postEvent(new CraterRegisterCommandEvent(event.getDispatcher())); + } + +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/mixin/BlockEntityMixin.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/mixin/BlockEntityMixin.java new file mode 100644 index 0000000..ea89701 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/mixin/BlockEntityMixin.java @@ -0,0 +1,57 @@ +package com.hypherionmc.craterlib.mixin; + +import com.hypherionmc.craterlib.api.blockentity.caps.CraterCapabilityHandler; +import com.hypherionmc.craterlib.api.blockentity.caps.ICraterCapProvider; +import com.hypherionmc.craterlib.common.blockentity.CraterBlockEntity; +import com.hypherionmc.craterlib.core.systems.energy.CustomEnergyStorage; +import com.hypherionmc.craterlib.core.systems.fluid.ICraterFluidHandler; +import com.hypherionmc.craterlib.core.systems.inventory.SimpleInventory; +import com.hypherionmc.craterlib.systems.energy.NeoForgeEnergyWrapper; +import com.hypherionmc.craterlib.systems.fluid.NeoForgeWrappedFluidTank; +import com.hypherionmc.craterlib.systems.inventory.NeoForgeInventoryWrapper; +import net.minecraft.core.Direction; +import net.neoforged.neoforge.common.capabilities.Capabilities; +import net.neoforged.neoforge.common.capabilities.Capability; +import net.neoforged.neoforge.common.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.common.util.LazyOptional; +import net.neoforged.neoforge.items.wrapper.SidedInvWrapper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.Optional; + +/** + * @author HypherionSA + */ +@Mixin(CraterBlockEntity.class) +public class BlockEntityMixin implements ICapabilityProvider { + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + ICraterCapProvider capProvider = (ICraterCapProvider) this; + + if (cap == Capabilities.ENERGY) { + Optional forgeCap = capProvider.getCapability(CraterCapabilityHandler.ENERGY, side); + if (forgeCap.isPresent()) { + return LazyOptional.of(() -> new NeoForgeEnergyWrapper(forgeCap.get())).cast(); + } + } + + if (cap == Capabilities.ITEM_HANDLER) { + Optional inventory = capProvider.getCapability(CraterCapabilityHandler.ITEM, side); + if (inventory.isPresent()) { + return LazyOptional.of(() -> new SidedInvWrapper(new NeoForgeInventoryWrapper(inventory.get()), side)).cast(); + } + } + + if (cap == Capabilities.FLUID_HANDLER) { + Optional fluidTank = capProvider.getCapability(CraterCapabilityHandler.FLUID, side); + if (fluidTank.isPresent()) { + return LazyOptional.of(() -> (NeoForgeWrappedFluidTank)fluidTank.get()).cast(); + } + } + + return LazyOptional.empty(); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/mixin/ConfigScreenHandlerMixin.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/mixin/ConfigScreenHandlerMixin.java new file mode 100644 index 0000000..90228bf --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/mixin/ConfigScreenHandlerMixin.java @@ -0,0 +1,44 @@ +package com.hypherionmc.craterlib.mixin; + +import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen; +import com.hypherionmc.craterlib.core.config.ConfigController; +import com.hypherionmc.craterlib.core.config.ModuleConfig; +import com.hypherionmc.craterlib.core.config.annotations.NoConfigScreen; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.neoforged.neoforge.client.ConfigScreenHandler; +import net.neoforged.neoforgespi.language.IModInfo; +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; + +import java.util.Optional; +import java.util.function.BiFunction; + +/** + * @author HypherionSA + */ +@Mixin(ConfigScreenHandler.class) +public class ConfigScreenHandlerMixin { + + /** + * Inject Auto Generated config Screens into forge + * @param selectedMod + * @param cir + */ + @Inject(at = @At("RETURN"), method = "getScreenFactoryFor", cancellable = true, remap = false) + private static void injectConfigScreen(IModInfo selectedMod, CallbackInfoReturnable>> cir) { + ConfigController.getMonitoredConfigs().forEach((conf, watcher) -> { + if (!conf.getClass().isAnnotationPresent(NoConfigScreen.class)) { + ModuleConfig config = (ModuleConfig) conf; + if (config.getModId().equals(selectedMod.getModId())) { + cir.setReturnValue( + Optional.of((minecraft, screen) -> new CraterConfigScreen(config, screen)) + ); + } + } + }); + } + +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/network/NeoForgeNetworkHandler.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/network/NeoForgeNetworkHandler.java new file mode 100644 index 0000000..3c77462 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/network/NeoForgeNetworkHandler.java @@ -0,0 +1,127 @@ +package com.hypherionmc.craterlib.network; + +import com.google.common.collect.Maps; +import com.hypherionmc.craterlib.core.network.CraterNetworkHandler; +import com.hypherionmc.craterlib.core.network.CraterPacket; +import com.hypherionmc.craterlib.core.network.PacketDirection; +import com.hypherionmc.craterlib.core.platform.ClientPlatform; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.Packet; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.neoforged.fml.LogicalSide; +import net.neoforged.neoforge.common.util.LogicalSidedProvider; +import net.neoforged.neoforge.network.NetworkEvent; +import net.neoforged.neoforge.network.NetworkRegistry; +import net.neoforged.neoforge.network.PlayNetworkDirection; +import net.neoforged.neoforge.network.simple.MessageFunctions; +import net.neoforged.neoforge.network.simple.SimpleChannel; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * @author HypherionSA + * Partly inspired by and based on ... + */ +public class NeoForgeNetworkHandler implements CraterNetworkHandler { + + private static final Map NETWORK_HANDLERS = Maps.newConcurrentMap(); + private static final String PROTOCOL = Integer.toString(1); + + private final SimpleChannel channel; + + private final boolean clientRequired; + + private final boolean serverRequired; + + private final AtomicInteger packetID = new AtomicInteger(); + + private NeoForgeNetworkHandler(SimpleChannel channel, boolean clientRequired, boolean serverRequired) { + this.channel = channel; + this.clientRequired = clientRequired; + this.serverRequired = serverRequired; + } + + @Override + public > void registerPacket(Class clazz, Supplier supplier, PacketDirection packetDirection) { + BiConsumer encoder = CraterPacket::write; + Function decoder = buf -> { + T packet = supplier.get(); + packet.read(buf); + return packet; + }; + + BiConsumer handler = (packet, ctx) -> { + LogicalSide expectedSide = getSideFromDirection(packetDirection); + LogicalSide currentSide = ctx.getDirection().getReceptionSide(); + + if (expectedSide != currentSide) { + throw new IllegalStateException(String.format("Received message on wrong side, expected %s, was %s", expectedSide, currentSide)); + } + + ctx.enqueueWork(() -> { + Player player; + if (packetDirection == PacketDirection.TO_CLIENT) { + player = ClientPlatform.INSTANCE.getClientPlayer(); + } else { + player = ctx.getSender(); + } + packet.handle(player, LogicalSidedProvider.WORKQUEUE.get(expectedSide)); + }); + ctx.setPacketHandled(true); + }; + + this.channel.registerMessage(this.packetID.getAndIncrement(), clazz, encoder(encoder), decoder(decoder), buildHandler(handler)); + } + + @Override + public Packet toServerBound(CraterPacket packet) { + return this.channel.toVanillaPacket(packet, PlayNetworkDirection.PLAY_TO_SERVER); + } + + @Override + public Packet toClientBound(CraterPacket packet) { + return this.channel.toVanillaPacket(packet, PlayNetworkDirection.PLAY_TO_CLIENT); + } + + @Override + public void sendToServer(CraterPacket packet) { + CraterNetworkHandler.super.sendToServer(packet); + } + + public synchronized static CraterNetworkHandler of(String modId, boolean clientRequired, boolean serverRequired) { + NeoForgeNetworkHandler handler = NETWORK_HANDLERS.computeIfAbsent(modId, modId1 -> new NeoForgeNetworkHandler(buildSimpleChannel(modId1, clientRequired, serverRequired), clientRequired, serverRequired)); + if (handler.clientRequired != clientRequired) throw new IllegalArgumentException("client channel settings mismatch, expected %s, but was %s".formatted(handler.clientRequired, clientRequired)); + if (handler.serverRequired != serverRequired) throw new IllegalArgumentException("server channel settings mismatch, expected %s, but was %s".formatted(handler.serverRequired, serverRequired)); + return handler; + } + + private static SimpleChannel buildSimpleChannel(String modId, boolean clientAcceptsVanillaOrMissing, boolean serverAcceptsVanillaOrMissing) { + return NetworkRegistry.ChannelBuilder + .named(new ResourceLocation(modId, "crater_network")) + .networkProtocolVersion(() -> PROTOCOL) + .clientAcceptedVersions(clientAcceptsVanillaOrMissing ? NetworkRegistry.acceptMissingOr(PROTOCOL) : PROTOCOL::equals) + .serverAcceptedVersions(serverAcceptsVanillaOrMissing ? NetworkRegistry.acceptMissingOr(PROTOCOL) : PROTOCOL::equals) + .simpleChannel(); + } + + private LogicalSide getSideFromDirection(PacketDirection direction) { + return direction == PacketDirection.TO_CLIENT ? LogicalSide.CLIENT : LogicalSide.SERVER; + } + + private MessageFunctions.MessageEncoder encoder(BiConsumer encoder) { + return encoder::accept; + } + + private MessageFunctions.MessageDecoder decoder(Function decoder) { + return decoder::apply; + } + + private MessageFunctions.MessageConsumer buildHandler(BiConsumer handler) { + return (message, ctx) -> handler.accept(message, ctx); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/energy/NeoForgeEnergyReader.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/energy/NeoForgeEnergyReader.java new file mode 100644 index 0000000..6c824bb --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/energy/NeoForgeEnergyReader.java @@ -0,0 +1,37 @@ +package com.hypherionmc.craterlib.systems.energy; + +import com.hypherionmc.craterlib.core.systems.energy.ICraterEnergyStorage; +import net.neoforged.neoforge.energy.IEnergyStorage; + +public record NeoForgeEnergyReader(IEnergyStorage forgeStorage) implements ICraterEnergyStorage { + + @Override + public int receiveEnergy(int toReceive, boolean test) { + return forgeStorage.receiveEnergy(toReceive, test); + } + + @Override + public int extractEnergy(int toExtract, boolean test) { + return forgeStorage.extractEnergy(toExtract, test); + } + + @Override + public int getPowerLevel() { + return forgeStorage.getEnergyStored(); + } + + @Override + public int getMaxInput() { + return 0; + } + + @Override + public int getMaxOutput() { + return 0; + } + + @Override + public int getPowerCapacity() { + return forgeStorage().getMaxEnergyStored(); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/energy/NeoForgeEnergyWrapper.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/energy/NeoForgeEnergyWrapper.java new file mode 100644 index 0000000..2eeb70e --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/energy/NeoForgeEnergyWrapper.java @@ -0,0 +1,41 @@ +package com.hypherionmc.craterlib.systems.energy; + +import com.hypherionmc.craterlib.core.systems.energy.CustomEnergyStorage; +import net.neoforged.neoforge.energy.IEnergyStorage; + +/** + * @author HypherionSA + * Forge Energy Support on top of the custom system + */ +public record NeoForgeEnergyWrapper(CustomEnergyStorage storage) implements IEnergyStorage { + + @Override + public int receiveEnergy(int maxReceive, boolean simulate) { + return storage.receiveEnergy(maxReceive, simulate); + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + return storage.extractEnergy(maxExtract, simulate); + } + + @Override + public int getEnergyStored() { + return storage.getPowerLevel(); + } + + @Override + public int getMaxEnergyStored() { + return storage.getPowerCapacity(); + } + + @Override + public boolean canExtract() { + return storage.getMaxOutput() > 0; + } + + @Override + public boolean canReceive() { + return storage.getMaxInput() > 0; + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidReader.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidReader.java new file mode 100644 index 0000000..02e7ea4 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidReader.java @@ -0,0 +1,46 @@ +package com.hypherionmc.craterlib.systems.fluid; + +import com.hypherionmc.craterlib.core.systems.fluid.FluidHolder; +import com.hypherionmc.craterlib.core.systems.fluid.ICraterFluidHandler; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +public record NeoForgeFluidReader(IFluidHandler fluidHandler) implements ICraterFluidHandler { + + @Override + public int insert(FluidHolder fluidHolder, FluidAction action) { + return fluidHandler.fill(new FluidStack(fluidHolder.getFluid(), fluidHolder.getAmount()), action.simulate() ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE); + } + + @Override + public FluidHolder extract(FluidHolder fluidHolder, FluidAction action) { + FluidStack extracted = fluidHandler.drain(new FluidStack(fluidHolder.getFluid(), fluidHolder.getAmount()), action.simulate() ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE); + return new FluidHolder(extracted.getFluid(), extracted.getAmount()); + } + + @Override + public FluidHolder extract(int amount, FluidAction action) { + FluidStack extracted = fluidHandler.drain(amount, action.simulate() ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE); + return new FluidHolder(extracted.getFluid(), extracted.getAmount()); + } + + @Override + public boolean isTankEmpty() { + return false; + } + + @Override + public FluidHolder getFluidInTank() { + return FluidHolder.EMPTY; + } + + @Override + public int getTankLevel() { + return 0; + } + + @Override + public int getTankCapacity() { + return 0; + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidTankInteractor.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidTankInteractor.java new file mode 100644 index 0000000..c0c957b --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidTankInteractor.java @@ -0,0 +1,47 @@ +package com.hypherionmc.craterlib.systems.fluid; + +import com.hypherionmc.craterlib.core.systems.fluid.FluidHolder; +import com.hypherionmc.craterlib.core.systems.fluid.ICraterFluidHandler; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import org.jetbrains.annotations.NotNull; + +public record NeoForgeFluidTankInteractor(ICraterFluidHandler fluidHandler) implements IFluidHandler { + + @Override + public int getTanks() { + return 1; + } + + @Override + public @NotNull FluidStack getFluidInTank(int tank) { + return new FluidStack(fluidHandler.getFluidInTank().getFluid(), fluidHandler.getFluidInTank().getAmount()); + } + + @Override + public int getTankCapacity(int tank) { + return fluidHandler.getTankCapacity(); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return true; + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return fluidHandler.insert(new FluidHolder(resource.getFluid(), resource.getAmount()), action.simulate() ? ICraterFluidHandler.FluidAction.SIMULATE : ICraterFluidHandler.FluidAction.EXECUTE); + } + + @Override + public @NotNull FluidStack drain(FluidStack resource, FluidAction action) { + FluidHolder drained = fluidHandler.extract(new FluidHolder(resource.getFluid(), resource.getAmount()), action.simulate() ? ICraterFluidHandler.FluidAction.SIMULATE : ICraterFluidHandler.FluidAction.EXECUTE); + return new FluidStack(drained.getFluid(), drained.getAmount()); + } + + @Override + public @NotNull FluidStack drain(int maxDrain, FluidAction action) { + FluidHolder drained = fluidHandler.extract(maxDrain, action.simulate() ? ICraterFluidHandler.FluidAction.SIMULATE : ICraterFluidHandler.FluidAction.EXECUTE); + return new FluidStack(drained.getFluid(), drained.getAmount()); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidUtils.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidUtils.java new file mode 100644 index 0000000..2e3f7f6 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeFluidUtils.java @@ -0,0 +1,25 @@ +package com.hypherionmc.craterlib.systems.fluid; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.AbstractTexture; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; + +public class NeoForgeFluidUtils { + + public static TextureAtlasSprite getFluidTexture(FluidStack fluidStack, boolean still) { + IClientFluidTypeExtensions props = IClientFluidTypeExtensions.of(fluidStack.getFluid()); + ResourceLocation fluidStill = still ? props.getStillTexture(fluidStack) : props.getFlowingTexture(fluidStack); + AbstractTexture texture = Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_BLOCKS); + + if (texture instanceof TextureAtlas atlas) { + return atlas.getSprite(fluidStill); + } + + return null; + } + +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeWrappedFluidTank.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeWrappedFluidTank.java new file mode 100644 index 0000000..da3e105 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/fluid/NeoForgeWrappedFluidTank.java @@ -0,0 +1,79 @@ +package com.hypherionmc.craterlib.systems.fluid; + +import com.hypherionmc.craterlib.core.systems.fluid.CraterFluidTank; +import com.hypherionmc.craterlib.core.systems.fluid.FluidHolder; +import com.hypherionmc.craterlib.core.systems.fluid.ICraterFluidHandler; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.IFluidTank; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +public class NeoForgeWrappedFluidTank extends CraterFluidTank implements IFluidTank, IFluidHandler { + + public NeoForgeWrappedFluidTank(int capacity) { + super(capacity); + } + + public NeoForgeWrappedFluidTank(int capacity, Predicate predicate) { + super(capacity, p -> predicate.test(new FluidStack(p.getFluid(), p.getAmount()))); + } + + @Override + public @NotNull FluidStack getFluid() { + return new FluidStack(this.getFluidInTank().getFluid(), this.getTankLevel()); + } + + @Override + public int getFluidAmount() { + return this.getTankLevel(); + } + + @Override + public int getCapacity() { + return this.getTankCapacity(); + } + + @Override + public boolean isFluidValid(FluidStack stack) { + return this.isValidFluid(new FluidHolder(stack.getFluid(), stack.getAmount())); + } + + @Override + public int getTanks() { + return 1; + } + + @Override + public @NotNull FluidStack getFluidInTank(int tankInt) { + return new FluidStack(this.getFluidInTank().getFluid(), this.getTankLevel()); + } + + @Override + public int getTankCapacity(int tankInt) { + return this.getTankCapacity(); + } + + @Override + public boolean isFluidValid(int tankInt, @NotNull FluidStack stack) { + return this.isValidFluid(new FluidHolder(stack.getFluid(), stack.getAmount())); + } + + @Override + public int fill(FluidStack resource, IFluidHandler.FluidAction action) { + return this.insert(new FluidHolder(resource.getFluid(), resource.getAmount()), action.simulate() ? ICraterFluidHandler.FluidAction.SIMULATE : ICraterFluidHandler.FluidAction.EXECUTE); + } + + @Override + public @NotNull FluidStack drain(int maxDrain, IFluidHandler.FluidAction action) { + FluidHolder extracted = this.extract(maxDrain, action.simulate() ? ICraterFluidHandler.FluidAction.SIMULATE : ICraterFluidHandler.FluidAction.EXECUTE); + return new FluidStack(extracted.getFluid(), extracted.getAmount()); + } + + @Override + public @NotNull FluidStack drain(FluidStack resource, IFluidHandler.FluidAction action) { + FluidHolder holder = this.extract(new FluidHolder(resource.getFluid(), resource.getAmount()), action.simulate() ? ICraterFluidHandler.FluidAction.SIMULATE : ICraterFluidHandler.FluidAction.EXECUTE); + return new FluidStack(holder.getFluid(), holder.getAmount()); + } +} diff --git a/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/inventory/NeoForgeInventoryWrapper.java b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/inventory/NeoForgeInventoryWrapper.java new file mode 100644 index 0000000..1c5cc45 --- /dev/null +++ b/NeoForge/src/main/java/com/hypherionmc/craterlib/systems/inventory/NeoForgeInventoryWrapper.java @@ -0,0 +1,90 @@ +package com.hypherionmc.craterlib.systems.inventory; + +import com.google.common.base.Suppliers; +import com.hypherionmc.craterlib.core.systems.inventory.SimpleInventory; +import net.minecraft.core.Direction; +import net.minecraft.world.WorldlyContainer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; +import java.util.stream.IntStream; + +/** + * @author HypherionSA + */ +public class NeoForgeInventoryWrapper implements WorldlyContainer { + + private final SimpleInventory inventory; + private final Supplier slots = Suppliers.memoize(() -> IntStream.range(0, getContainerSize()).toArray()); + + public NeoForgeInventoryWrapper(SimpleInventory inventory) { + this.inventory = inventory; + } + + @Override + public int[] getSlotsForFace(Direction side) { + return slots.get(); + } + + @Override + public boolean canPlaceItemThroughFace(int slot, ItemStack stack, @Nullable Direction side) { + if (canPlaceItem(slot, stack)) { + ItemStack existing = getItem(slot); + return existing.getCount() < getMaxStackSize(); + } + + return false; + } + + @Override + public boolean canTakeItemThroughFace(int slot, ItemStack stack, Direction side) { + return true; + } + + @Override + public int getContainerSize() { + return inventory.getItemHandler().getContainerSize(); + } + + @Override + public boolean isEmpty() { + return inventory.getItemHandler().isEmpty(); + } + + @Override + public ItemStack getItem(int slot) { + return inventory.getItemHandler().getItem(slot); + } + + @Override + public ItemStack removeItem(int p_18942_, int p_18943_) { + return inventory.getItemHandler().removeItem(p_18942_, p_18943_); + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + return inventory.getItemHandler().removeItemNoUpdate(slot); + } + + @Override + public void setItem(int slot, ItemStack stack) { + inventory.getItemHandler().setItem(slot, stack); + } + + @Override + public void setChanged() { + inventory.getItemHandler().setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return inventory.getItemHandler().stillValid(player); + } + + @Override + public void clearContent() { + inventory.getItemHandler().clearContent(); + } +} diff --git a/NeoForge/src/main/resources/META-INF/accesstransformer.cfg b/NeoForge/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 0000000..bf1848b --- /dev/null +++ b/NeoForge/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.client.renderer.LevelRenderer$RenderChunkInfo diff --git a/NeoForge/src/main/resources/META-INF/mods.toml b/NeoForge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..c911e56 --- /dev/null +++ b/NeoForge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,31 @@ +modLoader = "javafml" +loaderVersion = "[1,)" +license = "MIT" +issueTrackerURL="https://github.com/firstdarkdev/craterLib/issues" + +[[mods]] +modId = "${mod_id}" +version = "${version}" +displayName = "${mod_name}" +displayURL="https://modrinth.com/mod/craterlib" +logoFile = "craterlib_logo.png" +#credits="Thanks for this example mod goes to Java" +authors = "${mod_author}, Zenith" +description = ''' +A library mod used by First Dark Development and HypherionSA Mods +''' +displayTest = "MATCH_VERSION" + +[[dependencies.${mod_id}]] +modId = "neoforge" +mandatory = true +versionRange = "[20.2,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${mod_id}]] +modId = "minecraft" +mandatory = true +versionRange = "[1.20.2,1.21)" +ordering = "NONE" +side = "BOTH" diff --git a/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform new file mode 100644 index 0000000..5bd719f --- /dev/null +++ b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ClientPlatform @@ -0,0 +1 @@ +com.hypherionmc.craterlib.client.NeoForgeClientHelper \ No newline at end of file diff --git a/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform new file mode 100644 index 0000000..6cb6efb --- /dev/null +++ b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CommonPlatform @@ -0,0 +1 @@ +com.hypherionmc.craterlib.common.NeoForgeCommonHelper \ No newline at end of file diff --git a/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper new file mode 100644 index 0000000..7c023ac --- /dev/null +++ b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.CraterFluidHelper @@ -0,0 +1 @@ +com.hypherionmc.craterlib.common.NeoForgeFluidHelper \ No newline at end of file diff --git a/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment new file mode 100644 index 0000000..9a41f05 --- /dev/null +++ b/NeoForge/src/main/resources/META-INF/services/com.hypherionmc.craterlib.core.platform.ModloaderEnvironment @@ -0,0 +1 @@ +com.hypherionmc.craterlib.common.NeoForgeLoaderHelper \ No newline at end of file diff --git a/NeoForge/src/main/resources/craterlib.neoforge.mixins.json b/NeoForge/src/main/resources/craterlib.neoforge.mixins.json new file mode 100644 index 0000000..fa60324 --- /dev/null +++ b/NeoForge/src/main/resources/craterlib.neoforge.mixins.json @@ -0,0 +1,17 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.hypherionmc.craterlib.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "BlockEntityMixin" + ], + "client": [ + "ConfigScreenHandlerMixin" + ], + "server": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/NeoForge/src/main/resources/craterlib_logo.png b/NeoForge/src/main/resources/craterlib_logo.png new file mode 100644 index 0000000..ce0159c Binary files /dev/null and b/NeoForge/src/main/resources/craterlib_logo.png differ diff --git a/gradle.properties b/gradle.properties index ffb956d..ad4bd34 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,6 +19,9 @@ fabric_api=0.89.0+1.20.2 # Forge forge_version=48.0.6 +# NeoForged +neoforge_version=64-beta + # Dependencies mod_menu_version=8.0.0-beta.2 moon_config=1.0.9 diff --git a/settings.gradle b/settings.gradle index f4aa48f..d9cb6b1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,3 +12,5 @@ pluginManagement { rootProject.name = 'CraterLib' include("Common", "Fabric", "Forge") +include 'NeoForge' +