diff --git a/build.gradle b/build.gradle index a381bb7cb..9262db9cd 100644 --- a/build.gradle +++ b/build.gradle @@ -431,9 +431,21 @@ allprojects { p -> def compatible_forgemc_versions = "${compatible_minecraft_versions}".replaceAll("\"", "").replaceAll("]", ",)") // println compatible_forgemc_versions + // Quilt's custom contributors system + // This has to be like + // "Person": "Developer", "Another person": "Developer" + def quilt_contributors = [] + def mod_author_list = mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",") + for (dev in mod_author_list) { + quilt_contributors.push("\"${dev.strip()}\": \"Developer\"") + } + quilt_contributors.reverse() +// println quilt_contributors.join(", ") + def replaceProperties = [ version : mod_version, mod_name : mod_readable_name, + group : maven_group, authors : mod_authors, description : mod_description, homepage : mod_homepage, @@ -443,7 +455,8 @@ allprojects { p -> minecraft_version : minecraft_version, compatible_minecraft_versions: compatible_minecraft_versions, compatible_forgemc_versions : compatible_forgemc_versions, - java_version : java_version + java_version : java_version, + quilt_contributors : "{"+quilt_contributors.join(", ")+"}" ] // The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties diff --git a/coreSubProjects b/coreSubProjects index e017d3d59..b03ea3933 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit e017d3d599f3362be35080be3c7bb96f3afc935d +Subproject commit b03ea39338382107c80b8586a5527d4c38308921 diff --git a/quilt/build.gradle b/quilt/build.gradle new file mode 100644 index 000000000..ca49917a1 --- /dev/null +++ b/quilt/build.gradle @@ -0,0 +1,137 @@ +plugins { + id "org.quiltmc.loom" version "0.12.+" +} + +loom { + accessWidenerPath = project(":common").file("src/main/resources/${accessWidenerVersion}.lod.accesswidener") + + // "runs" isn't required, but when we do need it then it can be useful + runs { + client { + client() + setConfigName("Quilt Client") + ideConfigGenerated(true) + runDir("run") + } + server { + server() + setConfigName("Quilt Server") + ideConfigGenerated(true) + runDir("run") + } + } +} + +remapJar { + // Set the input jar for the task, also valid for remapSourcesJar + inputFile = project(":quilt").file("build/libs/DistantHorizons-quilt-${rootProject.versionStr}-all.jar") +} + +configurations { + // The addModJar basically embeds the mod to the built jar + addModJar + include.extendsFrom addModJar + modImplementation.extendsFrom addModJar +} + +def addMod(path, enabled) { + if (enabled == "2") + dependencies { modImplementation(path) } + else if (enabled == "1") + dependencies { modCompileOnly(path) } +} + +dependencies { + minecraft "com.mojang:minecraft:${minecraft_version}" + mappings loom.layered() { + // Mojmap mappings + officialMojangMappings() + // Parchment mappings (it adds parameter mappings & javadoc) + parchment("org.parchmentmc.data:parchment-${rootProject.minecraft_version}:${rootProject.parchment_version}@zip") + } + // Quilt loader + modImplementation "org.quiltmc:quilt-loader:${rootProject.quilt_loader_version}" + + // Quilted Fabric API + modImplementation "org.quiltmc.quilted-fabric-api:quilted-fabric-api:${rootProject.quilted_api_version}" // For now until quilt has a better way of doing this, just use quilt's qfapi +// addModJar(fabricApi.module("fabric-events-interaction-v0", rootProject.quilted_api_version)) +// addModJar(fabricApi.module("fabric-lifecycle-events-v1", rootProject.quilted_api_version)) +// addModJar(fabricApi.module("fabric-key-binding-api-v1", rootProject.quilted_api_version)) +// addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.quilted_api_version)) +// addModJar(fabricApi.module("fabric-rendering-v1", rootProject.quilted_api_version)) // TODO: Remove this as it is only needed in 1 line (QuiltClientProxy) +// addModJar(fabricApi.module("fabric-api-base", rootProject.quilted_api_version)) + + // Mod Menu + modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}") + + + + // Starlight + addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight) + + // Phosphor + addMod("curse.maven:phosphor-372124:${rootProject.phosphor_version_fabric}", rootProject.enable_phosphor) + + // Sodium + addMod("maven.modrinth:sodium:${rootProject.sodium_version}", rootProject.enable_sodium) + + // Lithium + addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium) + + // Iris + addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris) + + // BCLib + addMod("com.github.paulevsGitch:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib) +} + + +task deleteResources(type: Delete) { + delete file("build/resources/main") +} + +processResources { + dependsOn(copyCoreResources) + dependsOn(copyAccessWidener) +} + +runClient { + dependsOn(copyCoreResources) + dependsOn(copyAccessWidener) + jvmArgs "-XX:-OmitStackTraceInFastThrow" + finalizedBy(deleteResources) +} + +//jar { +// classifier "dev" +//} + +sourcesJar { + def commonSources = project(":common").sourcesJar + dependsOn commonSources + from commonSources.archiveFile.map { zipTree(it) } + + def fabricLikeSources = project(":fabricLike").sourcesJar + dependsOn fabricLikeSources + from fabricLikeSources.archiveFile.map { zipTree(it) } +} + +//components.java { +// withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { +// skip() +// } +//} + +publishing { + publications { + mavenFabric(MavenPublication) { + artifactId = rootProject.mod_name + "-" + project.name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + } +} \ No newline at end of file diff --git a/quilt/src/main/java/com/seibel/lod/quilt/FabricClientProxy.java b/quilt/src/main/java/com/seibel/lod/quilt/FabricClientProxy.java new file mode 100644 index 000000000..21e827857 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/FabricClientProxy.java @@ -0,0 +1,253 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt; + +import com.seibel.lod.common.wrappers.McObjectConverter; +import com.seibel.lod.common.wrappers.world.ClientLevelWrapper; +import com.seibel.lod.core.api.internal.ClientApi; +import com.mojang.blaze3d.platform.InputConstants; +import com.seibel.lod.common.wrappers.chunk.ChunkWrapper; + +import com.seibel.lod.core.dependencyInjection.ModAccessorInjector; +import com.seibel.lod.core.dependencyInjection.SingletonInjector; +import com.seibel.lod.core.logging.DhLoggerBuilder; +import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor; +import com.seibel.lod.quilt.wrappers.modAccessor.SodiumAccessor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.event.player.AttackBlockCallback; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.TitleScreen; + +import java.util.HashSet; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.phys.HitResult; +import org.apache.logging.log4j.Logger; +import org.lwjgl.glfw.GLFW; + +/** + * This handles all events sent to the client, + * and is the starting point for most of the mod. + * + * @author coolGi + * @author Ran + * @version 11-23-2021 + */ +@Environment(EnvType.CLIENT) +public class FabricClientProxy +{ + private final ClientApi clientApi = ClientApi.INSTANCE; + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + // TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi + private static final int[] KEY_TO_CHECK_FOR = { GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8, GLFW.GLFW_KEY_P}; + + HashSet previouslyPressKeyCodes = new HashSet<>(); + + + + /** + * Registers Fabric Events + * @author Ran + */ + public void registerEvents() + { + LOGGER.info("Registering Fabric Client Events"); + + + /* Register the mod needed event callbacks */ + + // ClientTickEvent + ClientTickEvents.START_CLIENT_TICK.register((client) -> + { + //LOGGER.info("ClientTickEvent.START_CLIENT_TICK"); + ClientApi.INSTANCE.clientTickEvent(); + }); + + // ClientLevelLoadEvent - Done in MixinClientPacketListener + // ClientLevelUnloadEvent - Done in MixinClientPacketListener + + // ClientChunkLoadEvent + // TODO: Is using setClientLightReady one still better? + //#if PRE_MC_1_18_1 // in 1.18+, we use mixin hook in setClientLightReady(true) + ClientChunkEvents.CHUNK_LOAD.register((level, chunk) -> + { + ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level); + ClientApi.INSTANCE.clientChunkLoadEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + }); + + // (kinda) block break event + AttackBlockCallback.EVENT.register((player, level, interactionHand, blockPos, direction) -> + { + // if we have access to the server, use the chunk save event instead + if (MC.clientConnectedToDedicatedServer()) + { + // Since fabric doesn't have a client-side break-block API event, this is the next best thing + ChunkAccess chunk = level.getChunk(blockPos); + if (chunk != null) + { +// LOGGER.info("attack block at blockpos: " + blockPos); + + ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); + ClientApi.INSTANCE.clientChunkLoadEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + } + } + + // don't stop the callback + return InteractionResult.PASS; + }); + + // (kinda) block place event + UseBlockCallback.EVENT.register((player, level, hand, hitResult) -> + { + // if we have access to the server, use the chunk save event instead + if (MC.clientConnectedToDedicatedServer()) + { + // Since fabric doesn't have a client-side place-block API event, this is the next best thing + if (hitResult.getType() == HitResult.Type.BLOCK + && !hitResult.isInside()) + { + ChunkAccess chunk = level.getChunk(hitResult.getBlockPos()); + if (chunk != null) + { +// LOGGER.info("use block at blockpos: " + hitResult.getBlockPos()); + + ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); + ClientApi.INSTANCE.clientChunkLoadEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + } + } + } + + // don't stop the callback + return InteractionResult.PASS; + }); + + //#endif + // ClientChunkSaveEvent + ClientChunkEvents.CHUNK_UNLOAD.register((level, chunk) -> + { + ClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level); + ClientApi.INSTANCE.clientChunkSaveEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + }); + + // RendererStartupEvent - Done in MixinGameRenderer + // RendererShutdownEvent - Done in MixinGameRenderer + + SodiumAccessor sodiumAccessor = (SodiumAccessor) ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class); + + // ClientRenderLevelTerrainEvent + WorldRenderEvents.AFTER_SETUP.register((renderContext) -> + { + if (sodiumAccessor != null) + { + sodiumAccessor.levelWrapper = ClientLevelWrapper.getWrapper(renderContext.world()); + sodiumAccessor.mcModelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose()); + sodiumAccessor.mcProjectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix()); + sodiumAccessor.partialTicks = renderContext.tickDelta(); + } + else + { + clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()), + McObjectConverter.Convert(renderContext.matrixStack().last().pose()), + McObjectConverter.Convert(renderContext.projectionMatrix()), + renderContext.tickDelta()); + } + }); + + // Debug keyboard event + // FIXME: Use better hooks so it doesn't trigger even in text boxes + ClientTickEvents.END_CLIENT_TICK.register(client -> + { + if (client.player != null && isValidTime()) + { + onKeyInput(); + } + }); + } + + private boolean isValidTime() { return !(Minecraft.getInstance().screen instanceof TitleScreen); } + +// public void blockChangeEvent(LevelAccessor world, BlockPos pos) { +// if (!isValidTime()) return; +// IChunkWrapper chunk = new ChunkWrapper(world.getChunk(pos), world); +// DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType()); +// +// // recreate the LOD where the blocks were changed +// // TODO: serverApi.blockChangeEvent(chunk, dimType); +// } + + public void onKeyInput() + { + HashSet currentKeyDown = new HashSet<>(); + + // Note: Minecraft's InputConstants is same as GLFW Key values + //TODO: Use mixin to hook directly into the GLFW Keyboard event in minecraft KeyboardHandler + // Check all keys we need + for (int keyCode = GLFW.GLFW_KEY_A; keyCode <= GLFW.GLFW_KEY_Z; keyCode++) + { + if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode)) + { + currentKeyDown.add(keyCode); + } + } + + for (int keyCode : KEY_TO_CHECK_FOR) + { + if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode)) + { + currentKeyDown.add(keyCode); + } + } + + // Diff and trigger events + for (int keyCode : currentKeyDown) + { + if (!previouslyPressKeyCodes.contains(keyCode)) + { + ClientApi.INSTANCE.keyPressedEvent(keyCode); + } + } + + // Update the set + previouslyPressKeyCodes = currentKeyDown; + } + +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/FabricDedicatedServerMain.java b/quilt/src/main/java/com/seibel/lod/quilt/FabricDedicatedServerMain.java new file mode 100644 index 000000000..eb7591daf --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/FabricDedicatedServerMain.java @@ -0,0 +1,39 @@ +package com.seibel.lod.quilt; + +import com.seibel.lod.common.wrappers.DependencySetup; +import com.seibel.lod.common.wrappers.minecraft.MinecraftDedicatedServerWrapper; +import com.seibel.lod.core.util.LodUtil; +import net.fabricmc.api.DedicatedServerModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.minecraft.server.dedicated.DedicatedServer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Environment(EnvType.SERVER) +public class FabricDedicatedServerMain implements DedicatedServerModInitializer +{ + private static final Logger LOGGER = LogManager.getLogger(FabricDedicatedServerMain.class.getSimpleName()); + + public static FabricServerProxy server_proxy; + public boolean hasPostSetupDone = false; + + @Override + public void onInitializeServer() { + DependencySetup.createServerBindings(); + FabricMain.init(); + + server_proxy = new FabricServerProxy(true); + server_proxy.registerEvents(); + + ServerLifecycleEvents.SERVER_STARTING.register((server) -> { + if (hasPostSetupDone) return; + hasPostSetupDone = true; + LodUtil.assertTrue(server instanceof DedicatedServer); + MinecraftDedicatedServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer) server; + FabricMain.postInit(); + LOGGER.info("Dedicated server inited at {}", server.getServerDirectory()); + }); + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/FabricMain.java b/quilt/src/main/java/com/seibel/lod/quilt/FabricMain.java new file mode 100644 index 000000000..6bb74134c --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/FabricMain.java @@ -0,0 +1,94 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt; + +import com.seibel.lod.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; +import com.seibel.lod.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent; +import com.seibel.lod.common.LodCommonMain; +import com.seibel.lod.core.ModInfo; +import com.seibel.lod.core.config.Config; +import com.seibel.lod.core.DependencyInjection.ApiEventInjector; +import com.seibel.lod.core.dependencyInjection.ModAccessorInjector; +import com.seibel.lod.core.dependencyInjection.SingletonInjector; +import com.seibel.lod.core.logging.DhLoggerBuilder; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.*; +import com.seibel.lod.quilt.wrappers.modAccessor.BCLibAccessor; +import com.seibel.lod.quilt.wrappers.modAccessor.OptifineAccessor; +import com.seibel.lod.quilt.wrappers.modAccessor.SodiumAccessor; +import com.seibel.lod.quilt.wrappers.modAccessor.StarlightAccessor; +import com.seibel.lod.quilt.wrappers.FabricDependencySetup; + +import org.apache.logging.log4j.Logger; + +/** + * Initialize and setup the Mod.
+ * If you are looking for the real start of the mod + * check out the ClientProxy. + * + * @author coolGi + * @author Ran + * @version 9-2-2022 + */ +public class FabricMain +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + public static void postInit() { + LOGGER.info("Post-Initializing Mod"); + FabricDependencySetup.runDelayedSetup(); + + if (Config.Client.Graphics.FogQuality.disableVanillaFog.get() && SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib")) + ModAccessorInjector.INSTANCE.get(IBCLibAccessor.class).setRenderCustomFog(false); // Remove BCLib's fog + + LOGGER.info("Mod Post-Initialized"); + } + + + // This loads the mod after minecraft loads which doesn't causes a lot of issues + public static void init() + { + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null); + + LOGGER.info("Initializing Mod"); + LodCommonMain.startup(null); + FabricDependencySetup.createInitialBindings(); + LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION); + + if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("sodium")) { + ModAccessorInjector.INSTANCE.bind(ISodiumAccessor.class, new SodiumAccessor()); + } + if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("starlight")) { + ModAccessorInjector.INSTANCE.bind(IStarlightAccessor.class, new StarlightAccessor()); + } + if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("optifine")) { + ModAccessorInjector.INSTANCE.bind(IOptifineAccessor.class, new OptifineAccessor()); + } + if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib")) { + ModAccessorInjector.INSTANCE.bind(IBCLibAccessor.class, new BCLibAccessor()); + } + LOGGER.info(ModInfo.READABLE_NAME + " Initialized"); + + ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null); + + // Init config + // The reason im initialising in this rather than the post init process is cus im using this for the auto updater + LodCommonMain.initConfig(); + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/FabricServerProxy.java b/quilt/src/main/java/com/seibel/lod/quilt/FabricServerProxy.java new file mode 100644 index 000000000..24fe8dfdc --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/FabricServerProxy.java @@ -0,0 +1,140 @@ +package com.seibel.lod.quilt; + +import com.seibel.lod.common.networking.Networking; +import com.seibel.lod.common.wrappers.chunk.ChunkWrapper; +import com.seibel.lod.common.wrappers.world.ClientLevelWrapper; +import com.seibel.lod.common.wrappers.world.ServerLevelWrapper; +import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment; +import com.seibel.lod.core.api.internal.ServerApi; +import com.seibel.lod.core.logging.DhLoggerBuilder; +import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import org.apache.logging.log4j.Logger; + +import java.util.function.Supplier; + +/** + * This handles all events sent to the server, + * and is the starting point for most of the mod. + * + * @author Ran + * @author Tomlee + * @version 5-11-2022 + */ +public class FabricServerProxy +{ + private static final ServerApi SERVER_API = ServerApi.INSTANCE; + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + private final boolean isDedicated; + public static Supplier isGenerationThreadChecker = null; + + + + public FabricServerProxy(boolean isDedicated) + { + this.isDedicated = isDedicated; + } + + + + private boolean isValidTime() + { + if (isDedicated) + { + return true; + } + + //FIXME: This may cause init issue... + return !(Minecraft.getInstance().screen instanceof TitleScreen); + } + + private ClientLevelWrapper getClientLevelWrapper(ClientLevel level) { return ClientLevelWrapper.getWrapper(level); } + private ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); } + + /** Registers Fabric Events */ + public void registerEvents() + { + LOGGER.info("Registering Fabric Server Events"); + isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread; + + /* Register the mod needed event callbacks */ + + // TEST EVENT + //ServerTickEvents.END_SERVER_TICK.register(this::tester); + + // ServerTickEvent + ServerTickEvents.END_SERVER_TICK.register((server) -> SERVER_API.serverTickEvent()); + + // ServerWorldLoadEvent + //TODO: Check if both of these use the correct timed events. (i.e. is it 'ed' or 'ing' one?) + ServerLifecycleEvents.SERVER_STARTING.register((server) -> + { + if (isValidTime()) + { + ServerApi.INSTANCE.serverLoadEvent(isDedicated); + } + }); + // ServerWorldUnloadEvent + ServerLifecycleEvents.SERVER_STOPPED.register((server) -> + { + if (isValidTime()) + { + ServerApi.INSTANCE.serverUnloadEvent(); + } + }); + + // ServerLevelLoadEvent + ServerWorldEvents.LOAD.register((server, level) -> + { + if (isValidTime()) + { + ServerApi.INSTANCE.serverLevelLoadEvent(getServerLevelWrapper(level)); + } + }); + // ServerLevelUnloadEvent + ServerWorldEvents.UNLOAD.register((server, level) -> + { + if (isValidTime()) + { + ServerApi.INSTANCE.serverLevelUnloadEvent(getServerLevelWrapper(level)); + } + }); + + // ServerChunkLoadEvent + ServerChunkEvents.CHUNK_LOAD.register((server, chunk) -> + { + ILevelWrapper level = getServerLevelWrapper((ServerLevel) chunk.getLevel()); + if (isValidTime()) + { + ServerApi.INSTANCE.serverChunkLoadEvent( + new ChunkWrapper(chunk, chunk.getLevel(), level), + level); + } + }); + // ServerChunkSaveEvent - Done in MixinChunkMap + } + + // This just exists here for testing purposes, it'll be removed in the future + public void tester(MinecraftServer server) + { // I disabled the Networking functions for now so this will not work atm - coolGi + for (ServerPlayer player : server.getPlayerList().getPlayers()) + { + FriendlyByteBuf payload = Networking.createNew(); + payload.writeInt(1); + System.out.println("Sending int 1"); + Networking.send(player, payload); + } + } + +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/QuiltClientMain.java b/quilt/src/main/java/com/seibel/lod/quilt/QuiltClientMain.java new file mode 100644 index 000000000..3b01a24eb --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/QuiltClientMain.java @@ -0,0 +1,31 @@ +package com.seibel.lod.quilt; + +import com.seibel.lod.common.wrappers.DependencySetup; +import org.quiltmc.loader.api.ModContainer; +import org.quiltmc.loader.api.minecraft.ClientOnly; +import org.quiltmc.qsl.base.api.entrypoint.client.ClientModInitializer; +import org.quiltmc.qsl.lifecycle.api.client.event.ClientLifecycleEvents; + +@ClientOnly +public class QuiltClientMain implements ClientModInitializer +{ + public static FabricClientProxy client_proxy; + public static FabricServerProxy server_proxy; + + + // Do if implements ClientModInitializer + // This loads the mod before minecraft loads which causes a lot of issues + @Override + public void onInitializeClient(ModContainer mod) { + DependencySetup.createClientBindings(); + FabricMain.init(); + + server_proxy = new FabricServerProxy(false); + server_proxy.registerEvents(); + + client_proxy = new FabricClientProxy(); + client_proxy.registerEvents(); + + ClientLifecycleEvents.READY.register((mc) -> FabricMain.postInit()); + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/mixins/FabricMixinPlugin.java b/quilt/src/main/java/com/seibel/lod/quilt/mixins/FabricMixinPlugin.java new file mode 100644 index 000000000..a1e4a5db7 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/mixins/FabricMixinPlugin.java @@ -0,0 +1,62 @@ +package com.seibel.lod.quilt.mixins; + +import org.objectweb.asm.tree.ClassNode; +import org.quiltmc.loader.api.QuiltLoader; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +/** + * @author coolGi + * @author cortex + */ +// TODO: Move to common if possible +public class FabricMixinPlugin implements IMixinConfigPlugin { + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if (mixinClassName.contains(".mods.")) { // If the mixin wants to go into a mod then we check if that mod is loaded or not + return QuiltLoader.isModLoaded( + mixinClassName + // What these 2 regex's do is get the mod name that we are checking out of the mixinClassName + // Eg. "com.seibel.lod.mixins.mods.sodium.MixinSodiumChunkRenderer" turns into "sodium" + .replaceAll("^.*mods.", "") // Replaces everything before the mods + .replaceAll("\\..*$", "") // Replaces everything after the mod name + ); + } + return true; + } + + + @Override + public void onLoad(String mixinPackage) { + + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + + } + + @Override + public List getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } +} \ No newline at end of file diff --git a/quilt/src/main/java/com/seibel/lod/quilt/mixins/mods/sodium/MixinSodiumChunkRenderer.java b/quilt/src/main/java/com/seibel/lod/quilt/mixins/mods/sodium/MixinSodiumChunkRenderer.java new file mode 100644 index 000000000..dbb663c75 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/mixins/mods/sodium/MixinSodiumChunkRenderer.java @@ -0,0 +1,37 @@ +package com.seibel.lod.quilt.mixins.mods.sodium; + +import com.seibel.lod.core.api.internal.ClientApi; +import com.seibel.lod.core.dependencyInjection.ModAccessorInjector; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor; +import com.seibel.lod.quilt.wrappers.modAccessor.SodiumAccessor; +import me.jellysquid.mods.sodium.client.gl.device.CommandList; +import me.jellysquid.mods.sodium.client.render.chunk.ChunkCameraContext; +import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderList; +import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderMatrices; +import me.jellysquid.mods.sodium.client.render.chunk.RegionChunkRenderer; +import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(RegionChunkRenderer.class) +public class MixinSodiumChunkRenderer { + @Unique SodiumAccessor accessor = null; + @Inject(remap = false, method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/ShaderChunkRenderer;begin(Lme/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass;)V", shift = At.Shift.AFTER)) + private void injectDHLoDRendering(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderList list, BlockRenderPass pass, ChunkCameraContext camera, CallbackInfo ci) { + if (accessor == null) { + accessor = (SodiumAccessor)ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class); + } + if (pass.equals(BlockRenderPass.SOLID)) { + //TODO: use matrices.modelView() and matrices.projection() instead of + // SodiumAccessor.mcModelViewMatrix, + // SodiumAccessor.mcProjectionMatrix, + ClientApi.INSTANCE.renderLods(accessor.levelWrapper, + accessor.mcModelViewMatrix, + accessor.mcProjectionMatrix, + accessor.partialTicks); + } + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/mixins/server/MixinUtilBackgroundThread.java b/quilt/src/main/java/com/seibel/lod/quilt/mixins/server/MixinUtilBackgroundThread.java new file mode 100644 index 000000000..b8ebbbdee --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/mixins/server/MixinUtilBackgroundThread.java @@ -0,0 +1,73 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.mixins.server; + +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; + +import com.seibel.lod.quilt.FabricServerProxy; +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 com.seibel.lod.core.util.objects.DummyRunExecutorService; + +import net.minecraft.Util; + +@Mixin(Util.class) +public class MixinUtilBackgroundThread +{ + @Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true) + private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable ci) + { + if (FabricServerProxy.isGenerationThreadChecker != null && FabricServerProxy.isGenerationThreadChecker.get()) + { + //ApiShared.LOGGER.info("util backgroundExecutor triggered"); + ci.setReturnValue(new DummyRunExecutorService()); + } + } + + #if POST_MC_1_17_1 + @Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;", + at = @At("HEAD"), cancellable = true) + private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable ci) + { + if (FabricServerProxy.isGenerationThreadChecker != null && FabricServerProxy.isGenerationThreadChecker.get()) + { + //ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered"); + ci.setReturnValue(r); + } + } + #endif + #if POST_MC_1_18_1 + @Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;", + at = @At("HEAD"), cancellable = true) + private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier r, CallbackInfoReturnable> ci) + { + if (FabricServerProxy.isGenerationThreadChecker != null && FabricServerProxy.isGenerationThreadChecker.get()) + { + //ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered"); + ci.setReturnValue(r); + } + } + #endif + +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/FabricDependencySetup.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/FabricDependencySetup.java new file mode 100644 index 000000000..bd7145862 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/FabricDependencySetup.java @@ -0,0 +1,48 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.wrappers; + +import com.seibel.lod.core.dependencyInjection.SingletonInjector; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker; +import com.seibel.lod.quilt.wrappers.modAccessor.ModChecker; +import com.seibel.lod.fabriclike.wrappers.FabricLikeDependencySetup; + +/** + * Binds all necessary dependencies, so we + * can access them in Core.
+ * This needs to be called before any Core classes + * are loaded. + * + * @author James Seibel + * @author Ran + * @version 3-5-2022 + */ +public class FabricDependencySetup +{ + public static void createInitialBindings() { + SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE); + FabricLikeDependencySetup.createInitialBindings(); + } + + public static void runDelayedSetup() { + FabricLikeDependencySetup.runDelayedSetup(); + SingletonInjector.INSTANCE.runDelayedSetup(); + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/config/ModMenuIntegration.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/config/ModMenuIntegration.java new file mode 100644 index 000000000..2ccb4fafe --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/config/ModMenuIntegration.java @@ -0,0 +1,35 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.wrappers.config; + +import com.seibel.lod.common.wrappers.gui.GetConfigScreen; +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; + +/** + * For making the config show up in modmenu + */ +public class ModMenuIntegration implements ModMenuApi { + // For the custom config code + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parent -> GetConfigScreen.getScreen(parent); + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/BCLibAccessor.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/BCLibAccessor.java new file mode 100644 index 000000000..c54472d90 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/BCLibAccessor.java @@ -0,0 +1,25 @@ +package com.seibel.lod.quilt.wrappers.modAccessor; + +import com.seibel.lod.core.wrapperInterfaces.modAccessor.IBCLibAccessor; +import ru.bclib.config.ClientConfig; +import ru.bclib.config.Configs; +import ru.bclib.util.BackgroundInfo; + +import java.awt.*; + +public class BCLibAccessor implements IBCLibAccessor { + @Override + public String getModName() { + return "BCLib"; + } + + public void setRenderCustomFog(boolean newValue) { + // Change the value of CUSTOM_FOG_RENDERING in the bclib client config + Configs.CLIENT_CONFIG.set(ClientConfig.CUSTOM_FOG_RENDERING, newValue); + } + + @Override + public Color getFogColor() { + return new Color(BackgroundInfo.fogColorRed, BackgroundInfo.fogColorGreen, BackgroundInfo.fogColorBlue); + } +} \ No newline at end of file diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/ModChecker.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/ModChecker.java new file mode 100644 index 000000000..482f48d74 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/ModChecker.java @@ -0,0 +1,32 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.wrappers.modAccessor; + +import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker; +import org.quiltmc.loader.api.QuiltLoader; + +public class ModChecker implements IModChecker { + public static final ModChecker INSTANCE = new ModChecker(); + + @Override + public boolean isModLoaded(String modid) { + return QuiltLoader.isModLoaded(modid); + } +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/OptifineAccessor.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/OptifineAccessor.java new file mode 100644 index 000000000..74f4af83e --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/OptifineAccessor.java @@ -0,0 +1,44 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.wrappers.modAccessor; + +import java.util.HashSet; + +import com.seibel.lod.core.pos.DhChunkPos; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor; + +public class OptifineAccessor extends AbstractOptifineAccessor +{ + + @Override + public String getModName() + { + return "Optifine-Fabric-1.18.X"; + } + + @Override + public HashSet getNormalRenderedChunks() + { + // TODO: Impl proper methods here + return null; + } + +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/SodiumAccessor.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/SodiumAccessor.java new file mode 100644 index 000000000..eb0a86860 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/SodiumAccessor.java @@ -0,0 +1,122 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.wrappers.modAccessor; + +import java.util.HashSet; +import java.util.stream.Collectors; + +import com.seibel.lod.core.pos.DhChunkPos; +import com.seibel.lod.core.dependencyInjection.SingletonInjector; +import com.seibel.lod.core.util.math.Mat4f; +import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; +import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor; + + +import com.seibel.lod.core.wrapperInterfaces.world.IClientLevelWrapper; +import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer; +import net.minecraft.client.Minecraft; +#if PRE_MC_1_17_1 +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.phys.AABB; +#else +import net.minecraft.world.level.LevelHeightAccessor; +#endif + +public class SodiumAccessor implements ISodiumAccessor { + private final IWrapperFactory factory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); + private final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + public IClientLevelWrapper levelWrapper; + public Mat4f mcModelViewMatrix; + public Mat4f mcProjectionMatrix; + public float partialTicks; + + @Override + public String getModName() { + return "Sodium-Fabric"; + } + + #if POST_MC_1_17_1 + @Override + public HashSet getNormalRenderedChunks() { + SodiumWorldRenderer renderer = SodiumWorldRenderer.instance(); + LevelHeightAccessor height = Minecraft.getInstance().level; + + #if POST_MC_1_18_1 + // 0b11 = Lighted chunk & loaded chunk + return renderer.getChunkTracker().getChunks(0b00).filter( + (long l) -> { + return true; + }).mapToObj(DhChunkPos::new).collect(Collectors.toCollection(HashSet::new)); + #else + // TODO: Maybe use a mixin to make this more efficient, and maybe ignore changes behind the camera + return MC_RENDER.getMaximumRenderedChunks().stream().filter((DHChunkPos chunk) -> { + return (renderer.isBoxVisible( + chunk.getMinBlockX()+1, height.getMinBuildHeight()+1, chunk.getMinBlockZ()+1, + chunk.getMinBlockX()+15, height.getMaxBuildHeight()-1, chunk.getMinBlockZ()+15)); + }).collect(Collectors.toCollection(HashSet::new)); + #endif + } + #else + @Override + public HashSet getNormalRenderedChunks() { + SodiumWorldRenderer renderer = SodiumWorldRenderer.getInstance(); + LevelAccessor height = Minecraft.getInstance().level; + // TODO: Maybe use a mixin to make this more efficient + return MC_RENDER.getMaximumRenderedChunks().stream().filter((DHChunkPos chunk) -> { + FakeChunkEntity AABB = new FakeChunkEntity(chunk.getX(), chunk.getZ(), height.getMaxBuildHeight()); + return (renderer.isEntityVisible(AABB)); + }).collect(Collectors.toCollection(HashSet::new)); + } + + private static class FakeChunkEntity extends Entity { + public int cx; + public int cz; + public int my; + public FakeChunkEntity(int chunkX, int chunkZ, int maxHeight) { + super(EntityType.AREA_EFFECT_CLOUD, null); + cx = chunkX; + cz = chunkZ; + my = maxHeight; + } + @Override + public AABB getBoundingBoxForCulling() { + return new AABB(cx*16+1, 1, cz*16+1, + cx*16+15, my-1, cz*16+15); + } + @Override + protected void defineSynchedData() {} + @Override + protected void readAdditionalSaveData(CompoundTag paramCompoundTag) {} + @Override + protected void addAdditionalSaveData(CompoundTag paramCompoundTag) {} + @Override + public Packet getAddEntityPacket() { + throw new UnsupportedOperationException("This is a FAKE CHUNK ENTITY... For tricking the Sodium to check a AABB."); + } + } + #endif + +} diff --git a/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/StarlightAccessor.java b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/StarlightAccessor.java new file mode 100644 index 000000000..bfee01f18 --- /dev/null +++ b/quilt/src/main/java/com/seibel/lod/quilt/wrappers/modAccessor/StarlightAccessor.java @@ -0,0 +1,35 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.quilt.wrappers.modAccessor; + +import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor; + + +public class StarlightAccessor implements IStarlightAccessor { + + @Override + public String getModName() { + return "Starlight-Fabric-1.18.X"; + } + + public StarlightAccessor() { + + } +} diff --git a/quilt/src/main/resources/DistantHorizons.quilt.mixins.json b/quilt/src/main/resources/DistantHorizons.quilt.mixins.json new file mode 100644 index 000000000..41fcd37e3 --- /dev/null +++ b/quilt/src/main/resources/DistantHorizons.quilt.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.seibel.lod.quilt.mixins", + "mixins": [ + "server.MixinUtilBackgroundThread" + ], + "client": [ + "mods.sodium.MixinSodiumChunkRenderer" + ], + "injectors": { + "defaultRequire": 1 + }, + "plugin": "com.seibel.lod.quilt.mixins.FabricMixinPlugin" +} diff --git a/quilt/src/main/resources/quilt.mod.json b/quilt/src/main/resources/quilt.mod.json new file mode 100644 index 000000000..e8ab639f5 --- /dev/null +++ b/quilt/src/main/resources/quilt.mod.json @@ -0,0 +1,75 @@ +{ + "schema_version": 1, + "quilt_loader": { + "group": "${group}", + "id": "lod", + "version": "${version}", + + "metadata": { + "name": "${mod_name}", + "description": "${description}", + "contributors": $quilt_contributors, + + "contact": { + "homepage": "${homepage}", + "sources": "${source}", + "issues": "${issues}" + }, + + "license": "LGPL-3.0", + "icon": "icon.png" + }, + + "intermediate_mappings": "net.fabricmc:intermediary", + + + "entrypoints": { + "client_init": [ + "com.seibel.lod.quilt.QuiltClientMain" + ], + "server": [ + "com.seibel.lod.quilt.FabricDedicatedServerMain" + ], + + "modmenu": [ + "com.seibel.lod.quilt.wrappers.config.ModMenuIntegration" + ] + }, + + + "depends": [ + "quilt_loader", + "quilted_fabric_api_base", + "quilted_fabric_lifecycle_events_v1", + "quilted_fabric_key_binding_api_v1", + "quilted_fabric_key_binding_api_v1", + "quilted_fabric_resource_loader_v0", + { + "id": "minecraft", + "versions": $compatible_minecraft_versions + }, + { + "id": "java", + "versions": ">=${java_version}" + } + ] + }, + "access_widener": "lod.accesswidener", + + "mixins": [ + "DistantHorizons.fabricLike.mixins.json", + "DistantHorizons.quilt.mixins.json" + ], + + "minecraft": { + "environment": "*" + }, + + "custom": { + "modmenu": { + "links": { + "modmenu.discord": "${discord}" + } + } + } +} diff --git a/settings.gradle b/settings.gradle index ceb9668f2..35ddae696 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,7 +8,7 @@ pluginManagement { name "Forge" url "https://maven.minecraftforge.net/" } - maven { // We may not use Quilt atm, but better to have it here for when it eventually gets added + maven { name "Quilt" url "https://maven.quiltmc.org/repository/release" } diff --git a/versionProperties/1.18.2.properties b/versionProperties/1.18.2.properties index bff4be51a..a9f69810a 100644 --- a/versionProperties/1.18.2.properties +++ b/versionProperties/1.18.2.properties @@ -4,7 +4,7 @@ minecraft_version=1.18.2 parchment_version=2022.11.06 compatible_minecraft_versions=["1.18.2"] accessWidenerVersion=1_18 -builds_for=["fabric", "forge"] +builds_for=["fabric", "quilt", "forge"] # Fabric loader fabric_loader_version=0.14.14 @@ -33,6 +33,14 @@ fabric_api_version=0.67.1+1.18.2 enable_bclib=1 enable_canvas=0 +quilt_loader_version=0.18.4-pre.1-SNAPSHOT +quilted_api_version=1.0.0-beta.9+0.51.1-1.18.2-SNAPSHOT + # Quilt mod versions + ### Most of the time quilt uses the same stuff as fabric, so this is empty atm ### + + # Quilt mod versions + ### Idk what you expected, sutch empty ### + # Forge loader # TODO: Update forge forge_version=40.0.32