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