diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index a190fb110..000000000 --- a/.dockerignore +++ /dev/null @@ -1,19 +0,0 @@ -**/.git -**/.gitlab -**/.cache - -buildAllJars - -**/_Misc Files -*.bat -*.md -*.sh -*.txt - -coreSubProjects/*.md -coreSubProjects/*.txt - -**/.gitignore -**/.gitattributes -**/.gitlab-cy.yml -**/.gitmodules diff --git a/.run/distant-horizons [cleanroom_runClient].run.xml b/.run/distant-horizons [cleanroom_runClient].run.xml new file mode 100644 index 000000000..5fb0dac77 --- /dev/null +++ b/.run/distant-horizons [cleanroom_runClient].run.xml @@ -0,0 +1,27 @@ + + + + + + + true + true + false + false + false + false + false + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 3044ee64e..000000000 --- a/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM eclipse-temurin:25-jdk - -WORKDIR /home/build/ -COPY ./gradlew . -RUN chmod +x ./gradlew -CMD echo "\r========== [CLEAN: $MC_VER] ==========" && \ - ./gradlew clean -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \ - echo "\r========== [BUILD: $MC_VER] ==========" && \ - ./gradlew build -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \ - echo "\r========== [MERGE: $MC_VER] ==========" && \ - ./gradlew mergeJars -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \ - echo "\r========== [DONE: $MC_VER] ==========" diff --git a/build.gradle b/build.gradle index 982ccf12c..af874eef2 100644 --- a/build.gradle +++ b/build.gradle @@ -4,10 +4,10 @@ plugins { } forgix { - autoRun = true // add the mod loaders to the end of the jar // put together in the format: "a", "a-b", "a-b-c" + int loaderCount = 0; String modLoaders = ""; ((String) gradle.builds_for) .split(",") @@ -20,7 +20,13 @@ forgix { } modLoaders += loaderName; + + loaderCount++; } + + // run if there are multiple launchers that need merging + autoRun = (loaderCount > 1); + // merged jars are named in the format: // "DistantHorizons-3.0.1-b-dev-26.1-fabric-neoforge.jar" archiveClassifier = modLoaders diff --git a/buildSrc/src/main/groovy/dh-loader.gradle b/buildSrc/src/main/groovy/dh-loader.gradle index 838e869ce..852d42f23 100644 --- a/buildSrc/src/main/groovy/dh-loader.gradle +++ b/buildSrc/src/main/groovy/dh-loader.gradle @@ -6,6 +6,7 @@ import org.apache.tools.zip.ZipOutputStream import javax.annotation.Nonnull import java.util.function.Function import java.util.function.Predicate +import groovy.json.JsonSlurper // Convention plugin for all MC-facing subprojects (common + loaders). // Common uses this directly; loaders use it via unimined-fabric/forge/neoforge. @@ -23,6 +24,9 @@ plugins { def isNotCommonProject = project.name != "common" +if (isNotCommonProject) { + evaluationDependsOn(":common") +} // ==================== Version Properties ==================== @@ -54,7 +58,12 @@ repositories { url "https://www.cursemaven.com" content { includeGroup "curse.maven" } } - maven { url "https://repo.spongepowered.org/maven/" } + maven { + url "https://repo.spongepowered.org/maven/" + // exclusion is needed since sponge has a deprecated version of fabric + // that gradle would prefer to get over the up-to-date version modrinth provides + content { excludeGroupByRegex "net\\.fabricmc(\\..*)?" } + } maven { url "https://maven.terraformersmc.com/" } maven { url "https://maven.neoforged.net/releases/" } flatDir { @@ -116,6 +125,15 @@ if (isNotCommonProject) { 'Multi-Release': true, 'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain', ) + if (project.name == "cleanroom") { + attributes( + 'ModType': 'CRL', + 'MixinConfigs': "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json", + 'FMLCorePlugin': 'com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin', + 'FMLCorePluginContainsFMLMod': true, + 'FMLAT': "src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons_at.cfg" + ) + } } } } @@ -128,8 +146,14 @@ unimined.minecraft(sourceSets.main, true) { if (gradle.ext.minecraft_version.startsWith("1.")) { // 26.1+ doesn't use obfuscation mappings { - mojmap() - devNamespace "mojmap" + if(gradle.ext.minecraft_version.startsWith("1.12.2")){ + mcp("stable", "39-1.12") + } + else{ + mojmap() + devNamespace "mojmap" + } + } } } @@ -160,18 +184,22 @@ if (isNotCommonProject) { source(project(":common").sourceSets.main.allSource) } } else { - // Common: fabric for compilation + access widener, no jar remapping or runs unimined.minecraft { - fabric { - loader gradle.ext.fabric_loader_version - accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener") + if (gradle.ext.minecraft_version.equals("1.12.2")) { + cleanroom { + loader gradle.ext.cleanroom_loader_version + } + } else { + fabric { + loader gradle.ext.fabric_loader_version + accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener") + } } defaultRemapJar = false runs.off = true } } - // ==================== Configurations ==================== evaluationDependsOn(":core") @@ -341,12 +369,25 @@ if (isNotCommonProject) { def loaderPaths = configurations.minecraftLibraries.resolve().collect { it.path }.toSet() tasks.withType(JavaExec).configureEach { runTask -> dependsOn(shadowJar) - classpath = files(shadowJar.archiveFile) + classpath.filter { file -> - !file.path.contains(project.buildDir.path) && - !file.path.contains("core${File.separator}build") && - !file.path.contains("api${File.separator}build") && - !file.path.contains("common${File.separator}build") && - !(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path)) + if (project.name != "cleanroom") { + classpath = files(shadowJar.archiveFile) + classpath.filter { file -> + file != shadowJar.archiveFile.get().asFile && + !file.path.contains(project.buildDir.path) && + !file.path.contains("core${File.separator}build") && + !file.path.contains("api${File.separator}build") && + !file.path.contains("common${File.separator}build") && + !(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path)) + } + } else { + // For cleanroom, don't put shadow jar on app classpath. + // crl.dev.extrapath loads it via LaunchClassLoader instead. + classpath = classpath.filter { file -> + !file.path.contains(project.buildDir.path) && + !file.path.contains("core${File.separator}build") && + !file.path.contains("api${File.separator}build") && + !file.path.contains("common${File.separator}build") && + !(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path)) + } } // Shared run directory so all loaders use the same worlds @@ -361,6 +402,31 @@ if (isNotCommonProject) { !arg.startsWith("-XX:MaxGCPauseMillis") } runTask.jvmArgs = filteredArgs + + if(project.name == "forge" + || project.name == "neoforge" + || project.name == "cleanroom") + { + // fix (Neo)forge, Cleanroom debug running + doFirst { + def modsDir = rootProject.file("run/${isClient ? 'client' : 'server'}/mods") + modsDir.mkdirs() + + // Remove any stale DH jars before copying the fresh one + modsDir.listFiles()?.each({ file -> + if (file.name.startsWith(rootProject.mod_name)) + { + file.delete() + } + }); + + // Copy shadow jar into mods folder so (Neo)Forge discovers it properly + copy { + from shadowJar.archiveFile + into modsDir + } + } + } // JVM args runTask.jvmArgs( @@ -371,7 +437,8 @@ if (isNotCommonProject) { //"-XX:+ZGenerational", rootProject.minecraftMemoryJavaArg, ) - if (isClient) { + if (isClient) + { runTask.jvmArgs( "-Dminecraft.api.auth.host=https://nope.invalid", "-Dminecraft.api.account.host=https://nope.invalid", @@ -382,11 +449,23 @@ if (isNotCommonProject) { // use a consistent username for easier debugging in a given world (vs randomly teleporting to a new user each time the game boots) "--username", "Dev", // "--renderDebugLabels" is a Mojang command to show render names in RenderDoc - "--renderDebugLabels", + "--renderDebugLabels" + ) + + // enabling tracy causes constant memory growth so it isn't always desired + if (rootProject.minecraftEnableTracy == "true") + { // "--tracy" is a Mojang command to allow individual frames to be debugged using Tracy https://github.com/wolfpld/tracy/releases/tag/v0.13.1 - "--tracy") + runTask.args("--tracy") + } + + } } + + tasks.downgradeJar.inputFile.set(tasks.named("remapJar").flatMap { it.archiveFile }) + tasks.jar.finalizedBy(tasks.named("remapJar")) + tasks.named("remapJar").configure { finalizedBy(tasks.shadeDowngradedApi) } } } @@ -398,6 +477,7 @@ if (isNotCommonProject) { def resourceTargets = [ "build_info.json", "fabric.mod.json", + "mcmod.info", "quilt.mod.json", "META-INF/mods.toml", "META-INF/neoforge.mods.toml", @@ -408,6 +488,7 @@ if (isNotCommonProject) { // Quilt contributors def quilt_contributors = [] def mod_author_list = rootProject.mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",") + def cleanroom_author_list = rootProject.mod_authors.replace('[', '').replace(']', '').split(',').collect({ it.trim().replace('"', '') }).join('", "') for (dev in mod_author_list) { quilt_contributors.push("\"${dev.strip()}\": \"Developer\"") } @@ -425,9 +506,11 @@ if (isNotCommonProject) { def replaceProperties = [ version : rootProject.mod_version, + mod_id : rootProject.mod_id, mod_name : rootProject.mod_readable_name, group : rootProject.maven_group, authors : rootProject.mod_authors, + cleanroom_authors : cleanroom_author_list, description : rootProject.mod_description, homepage : rootProject.mod_homepage, source : rootProject.mod_source, @@ -445,6 +528,7 @@ if (isNotCommonProject) { fabric_incompatibility_list : rootProject.fabric_incompatibility_list, fabric_recommend_list : rootProject.fabric_recommend_list, neoforge_version_range : rootProject.neoforge_version_range, + logo_path : "assets/distanthorizons/icon.png" ] inputs.properties replaceProperties @@ -455,7 +539,7 @@ if (isNotCommonProject) { // Remove unused access wideners exclude { file -> - if (file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener") { + if ((file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")) { return true } return false @@ -475,6 +559,25 @@ if (isNotCommonProject) { from fileTree(project(":core").file("src/main/resources")) into project.file("build/resources/main") } + + tasks.register("convertJsonToLang") { + dependsOn(copyCoreResources) + + File input = project.file("build/resources/main/assets/distanthorizons/lang/en_us.json") + File output = project.file("build/resources/main/assets/distanthorizons/lang/en_us.lang") + inputs.file(input) + outputs.file(output) + doLast { + output.withWriter("UTF-8") { writer -> + writer.writeLine("#PARSE_ESCAPES") + new JsonSlurper() + .parse(input) + .each { key, value -> + writer.writeLine("${key}=${value.toString().replace("%", "%%").replace("\n", "\\n")}") + } + } + } + } // ==================== JVMDowngrader ==================== diff --git a/buildSrc/src/main/groovy/unimined-cleanroom.gradle b/buildSrc/src/main/groovy/unimined-cleanroom.gradle new file mode 100644 index 000000000..04112af95 --- /dev/null +++ b/buildSrc/src/main/groovy/unimined-cleanroom.gradle @@ -0,0 +1,15 @@ +plugins { + id 'dh-loader' +} + +unimined.minecraft { + cleanroom { + loader gradle.ext.cleanroom_loader_version + useToolchains = false + accessTransformer project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons_at.cfg") + runs.all { + systemProperty("crl.dev.mixin", "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json") + systemProperty("fml.coreMods.load", "com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin") + } + } +} \ No newline at end of file diff --git a/cleanroom/build.gradle b/cleanroom/build.gradle new file mode 100644 index 000000000..3f021d12b --- /dev/null +++ b/cleanroom/build.gradle @@ -0,0 +1,48 @@ +plugins { + id 'unimined-cleanroom' +} + + +// ==================== Mod Dependency Helper ==================== + +def addMod(path, enabled) { + if (enabled == "2") + dependencies { modImplementation(path) } + else if (enabled == "1") + dependencies { compileOnly(path) } +} + + +// ==================== Dependencies ==================== + +dependencies { + +} + + +// ==================== Tasks ==================== + +task deleteResources(type: Delete) { + delete file("build/resources/main") +} + +processResources { + rename '(.+_at.cfg)', 'META-INF/$1' + dependsOn(copyCoreResources) + dependsOn(convertJsonToLang) + // dependsOn(copyCommonLoaderResources) +} + +tasks.named('runClient') { + dependsOn(copyCoreResources) + // dependsOn(copyCommonLoaderResources) + finalizedBy(deleteResources) +} + +sourcesJar { + def commonSources = project(":common").sourcesJar + dependsOn commonSources + from commonSources.archiveFile.map { zipTree(it) } +} + + diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomClientProxy.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomClientProxy.java new file mode 100644 index 000000000..f8fa56352 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomClientProxy.java @@ -0,0 +1,251 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom; + +import com.seibel.distanthorizons.common.AbstractModInitializer; +import com.seibel.distanthorizons.common.util.ProxyUtil; +import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; +import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper; +import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; +import com.seibel.distanthorizons.core.api.internal.ClientApi; +import com.seibel.distanthorizons.core.api.internal.ServerApi; +import com.seibel.distanthorizons.core.api.internal.SharedApi; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.logging.DhLogger; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.logging.f3.F3Screen; +import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage; +import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; + +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender; +import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL32; + +import java.util.concurrent.AbstractExecutorService; + +public class CleanroomClientProxy implements AbstractModInitializer.IEventProxy +{ + private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class); + private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + + private static World GetEventLevel(WorldEvent e) { return e.getWorld(); } + + + @Override + public void registerEvents() + { + MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(FMLCommonHandler.instance()); + CleanroomPluginPacketSender.setPacketHandler(ClientApi.INSTANCE::pluginMessageReceived); + } + + + + //==============// + // world events // + //==============// + + @SubscribeEvent + public void clientLevelLoadEvent(WorldEvent.Load event) + { + LOGGER.info("level load"); + + World level = event.getWorld(); + if (!(level instanceof WorldClient clientLevel)) + { + return; + } + + IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel, true); + ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper); + } + + @SubscribeEvent + public void clientLevelUnloadEvent(WorldEvent.Unload event) + { + LOGGER.info("level unload"); + + World level = event.getWorld(); + if (!(level instanceof WorldClient clientLevel)) + { + return; + } + + IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel); + ClientApi.INSTANCE.clientLevelUnloadEvent(clientLevelWrapper); + } + + + + //==============// + // chunk events // + //==============// + //region + + @SubscribeEvent + public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event) + { + if (MC.clientConnectedToDedicatedServer()) + { + World level = event.getWorld(); + + ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level); + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ())) + { + return; + } + + AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) + { + executor.execute(() -> + { + Chunk chunk = level.getChunk(event.getPos()); + SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel); + }); + } + } + } + @SubscribeEvent + public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event) + { + if (MC.clientConnectedToDedicatedServer()) + { + World level = event.getWorld(); + + ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level); + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ())) + { + return; + } + + AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) + { + executor.execute(() -> + { + Chunk chunk = level.getChunk(event.getPos()); + SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel); + }); + } + } + } + + @SubscribeEvent + public void clientChunkLoadEvent(ChunkEvent.Load event) + { + if (MC.clientConnectedToDedicatedServer()) + { + ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event)); + IChunkWrapper chunkWrapper = new ChunkWrapper(event.getChunk(), wrappedLevel); + SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, wrappedLevel); + } + } + + //endregion + + + + //==============// + // key bindings // + //==============// + //region + + @SubscribeEvent + public void registerKeyBindings(InputEvent.KeyInputEvent event) + { + /* if (Minecraft.getMinecraft().player == null) + { + return; + } + if (event.getAction() != GLFW.GLFW_PRESS) + { + return; + } + + ClientApi.INSTANCE.keyPressedEvent(event.getKey());*/ + } + + //endregion + + + + //===========// + // rendering // + //===========// + //region + + @SubscribeEvent + public void afterLevelRenderEvent(TickEvent.RenderTickEvent event) + { + if (event.type.equals(TickEvent.RenderTickEvent.Type.RENDER)) + { + try + { + // should generally only need to be set once per game session + // allows DH to render directly to Optifine's level frame buffer, + // allowing better shader support + MinecraftRenderWrapper.INSTANCE.finalLevelFrameBufferId = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING); + } + catch (Exception | Error e) + { + LOGGER.error("Unexpected error in afterLevelRenderEvent: "+e.getMessage(), e); + } + } + } + + @SubscribeEvent + public void onRenderOverlay(RenderGameOverlayEvent.Text event) + { + Minecraft mc = Minecraft.getMinecraft(); + if (event.isCanceled() + || !mc.gameSettings.showDebugInfo) + { + return; + } + + F3Screen.addStringToDisplay(event.getRight()); + } + + //endregion + + + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomMain.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomMain.java new file mode 100644 index 000000000..3055d707b --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomMain.java @@ -0,0 +1,147 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom; + +import com.seibel.distanthorizons.cleanroom.modAccessor.ModChecker; +import com.seibel.distanthorizons.common.AbstractModInitializer; +import com.seibel.distanthorizons.common.commands.CommandInitializer; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator; +import com.seibel.distanthorizons.core.api.internal.ServerApi; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender; +import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; +import com.seibel.distanthorizons.coreapi.ModInfo; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeChunkManager; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.*; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; + + +import java.util.List; +import java.util.function.Consumer; + +/** + * Initialize and setup the Mod.
+ * If you are looking for the real start of the mod + * check out the ClientProxy. + */ +@Mod(modid = ModInfo.ID, name = ModInfo.NAME, version = ModInfo.VERSION) +public class CleanroomMain extends AbstractModInitializer +{ + @Mod.Instance + public static CleanroomMain instance; + + @Mod.EventHandler + public void preinit(FMLPreInitializationEvent event) + { + Configurator.setLevel("org.sqlite", Level.INFO); + ForgeChunkManager.setForcedChunkLoadingCallback(CleanroomMain.instance, (tickets, world) -> { }); + } + + @Mod.EventHandler + public void init(FMLInitializationEvent event) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) + { + this.onInitializeClient(); + } + else + { + this.onInitializeServer(); + } + } + + @Override + protected void createInitialSharedBindings() + { + SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE); + SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new CleanroomPluginPacketSender()); + } + @Override + protected void createInitialClientBindings() { /* no additional setup needed currently */ } + + @Override + protected IEventProxy createClientProxy() { return new CleanroomClientProxy(); } + + @Override + protected IEventProxy createServerProxy(boolean isDedicated) { return new CleanroomServerProxy(isDedicated); } + + @Override + protected void initializeModCompat() + { + + } + +/* @Override + protected void subscribeRegisterCommandsEvent(Consumer> eventHandler) + { MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); }); }*/ + + @Override + protected void subscribeClientStartedEvent(Runnable eventHandler) + { + // Just run the event handler, since there are no proper ClientLifecycleEvent for the client + // to signify readiness other than FmlClientSetupEvent + eventHandler.run(); + } + + @Mod.EventHandler + public void onServerStarting(FMLServerStartingEvent event) + { + event.registerServerCommand(CommandInitializer.initCommands()); + } + + @Mod.EventHandler + public void onServerAboutToStart(FMLServerAboutToStartEvent event) + { + if (eventHandlerStartServer != null) + { + eventHandlerStartServer.accept(event.getServer()); + } + } + + Consumer eventHandlerStartServer; + + @Override + protected void subscribeServerStartingEvent(Consumer eventHandler) + { + eventHandlerStartServer = eventHandler; + } + + @Override + protected void runDelayedSetup() { SingletonInjector.INSTANCE.runDelayedSetup(); } + + // ServerWorldLoadEvent + @Mod.EventHandler + public void dedicatedWorldLoadEvent(FMLServerAboutToStartEvent event) + { + ServerApi.INSTANCE.serverLoadEvent(event.getServer().isDedicatedServer()); + } + + // ServerWorldUnloadEvent + @Mod.EventHandler + public void serverWorldUnloadEvent(FMLServerStoppingEvent event) + { + ServerApi.INSTANCE.serverUnloadEvent(); + } +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomPluginPacketSender.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomPluginPacketSender.java new file mode 100644 index 000000000..05ed2c9c6 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomPluginPacketSender.java @@ -0,0 +1,115 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom; + +import com.seibel.distanthorizons.common.AbstractPluginPacketSender; +import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper; +import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage; +import com.seibel.distanthorizons.core.network.messages.MessageRegistry; +import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import net.minecraftforge.fml.relauncher.Side; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public class CleanroomPluginPacketSender extends AbstractPluginPacketSender +{ + public static final SimpleNetworkWrapper PLUGIN_CHANNEL = + NetworkRegistry.INSTANCE.newSimpleChannel( + AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE + ); + + public static void setPacketHandler(Consumer consumer) + { + setPacketHandler((player, message) -> consumer.accept(message)); + } + static BiConsumer consumerPacket; + public static void setPacketHandler(BiConsumer consumer) + { + PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.CLIENT); + PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.SERVER); + consumerPacket = consumer; + } + + @Override + public void sendToServer(AbstractNetworkMessage message) + { + PLUGIN_CHANNEL.sendToServer(new MessageWrapper(message)); + } + + @Override + public void sendToClient(EntityPlayerMP serverPlayer, AbstractNetworkMessage message) + { + PLUGIN_CHANNEL.sendTo(new MessageWrapper(message), serverPlayer); + } + + // Forge doesn't support using abstract classes + @SuppressWarnings({"ClassCanBeRecord", "RedundantSuppression"}) + public static class MessageWrapper implements IMessage + { + public AbstractNetworkMessage message; + + public MessageWrapper(AbstractNetworkMessage message) { this.message = message; } + + public MessageWrapper() + { + // For reflection + } + + @Override + public void fromBytes(ByteBuf buf) { + int messageId = buf.readByte(); + message = MessageRegistry.INSTANCE.createMessage(messageId); + message.decode(buf); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeByte(MessageRegistry.INSTANCE.getMessageId(message)); + message.encode(buf); + } + + public static class Handler implements IMessageHandler + { + @Override + public IMessage onMessage(MessageWrapper wrapper, MessageContext context) { + if (wrapper.message != null) + { + if (context.side == Side.SERVER) + { + consumerPacket.accept(ServerPlayerWrapper.getWrapper(context.getServerHandler().player), wrapper.message); + } + else { + consumerPacket.accept(null, wrapper.message); + } + } + return null; // No response needed + } + } + } + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomServerProxy.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomServerProxy.java new file mode 100644 index 000000000..2d88eaebe --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/CleanroomServerProxy.java @@ -0,0 +1,181 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom; + +import com.seibel.distanthorizons.common.AbstractModInitializer; +import com.seibel.distanthorizons.common.commands.CommandInitializer; +import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon; +import com.seibel.distanthorizons.common.util.ProxyUtil; +import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; +import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper; +import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; +import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator; +import com.seibel.distanthorizons.core.api.internal.ServerApi; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.logging.DhLogger; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.ForgeChunkManager; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.event.FMLServerStoppingEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +import java.lang.reflect.Field; + +import static com.seibel.distanthorizons.cleanroom.CleanroomMain.instance; + +public class CleanroomServerProxy implements AbstractModInitializer.IEventProxy +{ + private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class); + private static World GetEventLevel(WorldEvent e) { return e.getWorld(); } + + private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + private final ServerApi serverApi = ServerApi.INSTANCE; + private final boolean isDedicated; + + + + @Override + public void registerEvents() + { + MinecraftForge.EVENT_BUS.register(this); + FMLCommonHandler.instance().bus().register(this); + if (this.isDedicated) + { + PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived); + } + } + + + + //=============// + // constructor // + //=============// + //region + + public CleanroomServerProxy(boolean isDedicated) { this.isDedicated = isDedicated; } + + //endregion + + + + //========// + // events // + //========// + //region + + // ServerLevelLoadEvent + @SubscribeEvent + public void serverLevelLoadEvent(WorldEvent.Load event) + { + if (GetEventLevel(event) instanceof WorldServer) + { + this.serverApi.serverLevelLoadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event))); + } + } + + // ServerLevelUnloadEvent + @SubscribeEvent + public void serverLevelUnloadEvent(WorldEvent.Unload event) + { + if (GetEventLevel(event) instanceof WorldServer) + { + this.serverApi.serverLevelUnloadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event))); + } + } + + @SubscribeEvent + public void serverChunkLoadEvent(ChunkEvent.Load event) + { + ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event)); + IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), levelWrapper); + this.serverApi.serverChunkLoadEvent(chunk, levelWrapper); + } + + @SubscribeEvent + public void serverChunkSaveEvent(ChunkDataEvent.Save event) + { + if (event.getWorld() instanceof WorldServer worldServer) + { + MixinChunkMapCommon.onChunkSave(worldServer, event.getChunk()); + } + } + + @SubscribeEvent + public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event) + { this.serverApi.serverPlayerJoinEvent(getServerPlayerWrapper(event)); } + + @SubscribeEvent + public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event) + { this.serverApi.serverPlayerDisconnectEvent(getServerPlayerWrapper(event)); } + + @SubscribeEvent + public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event) + { + this.serverApi.serverPlayerLevelChangeEvent( + getServerPlayerWrapper(event), + getServerLevelWrapper(event.fromDim, event), + getServerLevelWrapper(event.toDim, event) + ); + } + + //endregion + + + + //================// + // helper methods // + //================// + //region + + private static ServerLevelWrapper getServerLevelWrapper(WorldServer level) { return ServerLevelWrapper.getWrapper(level); } + + private static ServerLevelWrapper getServerLevelWrapper(int dimensionId, PlayerEvent event) + { + MinecraftServer server = event.player.getServer(); + if (server == null) + { + LOGGER.error("getServerLevelWrapper: server is null for player {}", event.player.getName()); + return null; + } + return getServerLevelWrapper(server.getWorld(dimensionId)); + } + + private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event) + { return ServerPlayerWrapper.getWrapper((EntityPlayerMP) event.player); } + + //endregion + + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/DistantHorizonsConfigPlugin.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/DistantHorizonsConfigPlugin.java new file mode 100644 index 000000000..3a693feaf --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/DistantHorizonsConfigPlugin.java @@ -0,0 +1,56 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom; + +import net.minecraftforge.fml.common.Loader; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public class DistantHorizonsConfigPlugin implements IMixinConfigPlugin +{ + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public void onLoad(String mixinPackage) + { } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) + { +/* return switch (mixinClassName.split("\\.")[5]) { + case "mist" -> Loader.isModLoaded("mist"); + default -> true; + };*/ + return true; + } + + @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 classNode, String mixinClassName, IMixinInfo mixinInfo) { } + @Override public void postApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { } + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/DistantHorizonsLoadingPlugin.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/DistantHorizonsLoadingPlugin.java new file mode 100644 index 000000000..a604cba7f --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/DistantHorizonsLoadingPlugin.java @@ -0,0 +1,52 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom; + +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class DistantHorizonsLoadingPlugin implements IFMLLoadingPlugin +{ + @Override + public @Nullable String[] getASMTransformerClass() + { + return new String[0]; + } + @Override + public @Nullable String getModContainerClass() + { + return null; + } + @Override + public @Nullable String getSetupClass() + { + return null; + } + @Override + public void injectData(Map data) { } + @Override + public @Nullable String getAccessTransformerClass() + { + return null; + } + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinEntityRenderer.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinEntityRenderer.java new file mode 100644 index 000000000..bb9be72b2 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinEntityRenderer.java @@ -0,0 +1,84 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom.mixins.client; + +import com.seibel.distanthorizons.common.commonMixins.MixinVanillaFogCommon; +import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper; +import com.seibel.distanthorizons.core.api.internal.ClientApi; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.EntityRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.init.MobEffects; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public class MixinEntityRenderer +{ + @Shadow + @Final + private DynamicTexture lightmapTexture; + + @Shadow @Final private Minecraft mc; + @Shadow @Final private static Logger LOGGER; + private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F; + private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F; + + @Inject(at = @At("TAIL"), method = "updateLightmap") + public void onUpdateLightmap(float patrialTicks, CallbackInfo ci) + { + IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + if (mc == null || mc.getWrappedClientLevel() == null) + { + return; + } + + IClientLevelWrapper clientLevel = mc.getWrappedClientLevel(); + MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + renderWrapper.setLightmapId(lightmapTexture.getGlTextureId(), clientLevel); + } + + @Inject(at = @At("RETURN"), method = "setupFog") + private void disableSetupFog(int startCoords, float partialTicks, CallbackInfo ci) + { + boolean cancelFog = MixinVanillaFogCommon.cancelFog(startCoords, mc); + if (cancelFog) + { + GlStateManager.setFogStart(A_REALLY_REALLY_BIG_VALUE); + GlStateManager.setFogEnd(A_EVEN_LARGER_VALUE); + ClientApi.RENDER_STATE.vanillaFogEnabled = false; + } + else + { + ClientApi.RENDER_STATE.vanillaFogEnabled = true; + } + } +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinNetHandlerPlayClient.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinNetHandlerPlayClient.java new file mode 100644 index 000000000..3f99f5f7c --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinNetHandlerPlayClient.java @@ -0,0 +1,46 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom.mixins.client; + +import com.seibel.distanthorizons.core.api.internal.ClientApi; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.server.SPacketJoinGame; +import net.minecraft.util.text.ITextComponent; +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.CallbackInfo; + +@Mixin(NetHandlerPlayClient.class) +public class MixinNetHandlerPlayClient +{ + @Inject(method = "handleJoinGame", at = @At("RETURN")) + private void onHandleJoinGameEnd(SPacketJoinGame packet, CallbackInfo ci) + { + ClientApi.INSTANCE.onClientOnlyConnected(); + } + + @Inject(method = "onDisconnect", at = @At("RETURN")) + private void onDisconnect(ITextComponent reason, CallbackInfo ci) + { + ClientApi.INSTANCE.onClientOnlyDisconnected(); + } + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinOptionsScreen.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinOptionsScreen.java new file mode 100644 index 000000000..82fa8cb47 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinOptionsScreen.java @@ -0,0 +1,83 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom.mixins.client; + +import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen; +import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.coreapi.ModInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiOptions; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.ResourceLocation; +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; + +/** + * Adds a button to the menu to goto the config + * + * @author coolGi + * @version 12-02-2021 + */ +@Mixin(GuiOptions.class) +public class MixinOptionsScreen extends GuiScreen +{ + // Get the texture for the button + @Unique private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png"); + + @Unique private static final int button_id = 99; + + @Inject(at = @At("HEAD"), method = "initGui") + private void lodconfig$init(CallbackInfo ci) + { + if (Config.Client.showDhOptionsButtonInMinecraftUi.get()) + this.buttonList.add( + (new TexturedButtonWidget( + button_id, + // Where the button is on the screen + this.width / 2 - 180, this.height / 6 - 12, + // Width and height of the button + 20, 20, + // Offset + 0, 0, + // Some textuary stuff + 20, ICON_TEXTURE, 20, 40, + // Create the button and tell it where to go + // For now it goes to the client option by default + // Add a title to the button + ModInfo.ID + ".title"))); + + } + + @Inject(at = @At("HEAD"), method = "actionPerformed", cancellable = true) + private void lodconfig$actionPerformed(GuiButton button, CallbackInfo ci) + { + if (button.id == button_id) + { + Minecraft.getMinecraft().displayGuiScreen(GetConfigScreen.getScreen(this)); + ci.cancel(); + } + } + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinRenderGlobal.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinRenderGlobal.java new file mode 100644 index 000000000..44ba6e158 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/client/MixinRenderGlobal.java @@ -0,0 +1,81 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom.mixins.client; + +import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; +import com.seibel.distanthorizons.core.api.internal.ClientApi; +import com.seibel.distanthorizons.core.util.math.Mat4f; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.entity.Entity; +import net.minecraft.util.BlockRenderLayer; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(RenderGlobal.class) +public class MixinRenderGlobal +{ + @Shadow private WorldClient world; + + @Inject(method = "renderBlockLayer(Lnet/minecraft/util/BlockRenderLayer;DILnet/minecraft/entity/Entity;)I", at = @At("HEAD")) + private void renderChunkLayer(BlockRenderLayer blockLayerIn, double partialTicks, int pass, Entity entityIn, CallbackInfoReturnable cir) + { + if (blockLayerIn == BlockRenderLayer.SOLID) + { + float[] mcProjMatrixRaw = new float[16]; + GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, mcProjMatrixRaw); + ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw); + ClientApi.RENDER_STATE.mcProjectionMatrix.transpose(); + + float[] mcModelViewRaw = new float[16]; + GL11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, mcModelViewRaw); + ClientApi.RENDER_STATE.mcModelViewMatrix = new Mat4f(mcModelViewRaw); + ClientApi.RENDER_STATE.mcModelViewMatrix.transpose(); + + ClientApi.RENDER_STATE.partialTickTime = (float) partialTicks; + ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.world); + + int blendSrc = GL11.glGetInteger(GL11.GL_BLEND_SRC); + int blendDst = GL11.glGetInteger(GL11.GL_BLEND_DST); + int boundTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); + + ClientApi.INSTANCE.renderLods(); + + GL30.glBindVertexArray(0); + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); + GL20.glUseProgram(0); + + //Restore vanilla states + GlStateManager.depthFunc(GL11.GL_LEQUAL); + GlStateManager.bindTexture(boundTexture); + GlStateManager.tryBlendFuncSeparate(blendSrc, blendDst, GL11.GL_ONE, GL11.GL_ZERO); + + } + } +} \ No newline at end of file diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/server/MixinEntityPlayerMP.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/server/MixinEntityPlayerMP.java new file mode 100644 index 000000000..300cb53f5 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/mixins/server/MixinEntityPlayerMP.java @@ -0,0 +1,66 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom.mixins.server; + +import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.util.ITeleporter; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EntityPlayerMP.class) +public abstract class MixinEntityPlayerMP implements IMixinServerPlayer +{ + @Shadow + @Final + public MinecraftServer server; + + @Unique + @Nullable + private volatile WorldServer distantHorizons$dimensionChangeDestination; + + + + @Override + @Nullable + public WorldServer distantHorizons$getDimensionChangeDestination() + { return this.distantHorizons$dimensionChangeDestination; } + + @Inject(at = @At("HEAD"), method = "changeDimension(ILnet/minecraftforge/common/util/ITeleporter;)Lnet/minecraft/entity/Entity;") + public void setDimensionChangeDestination(int destinationDimensionID, ITeleporter teleporter, CallbackInfoReturnable cir) + { this.distantHorizons$dimensionChangeDestination = this.server.getWorld(destinationDimensionID); } + + @Inject(at = @At("RETURN"), method = "clearInvulnerableDimensionChange") + public void clearDimensionChangeDestination(CallbackInfo ci) + { this.distantHorizons$dimensionChangeDestination = null; } + + + +} diff --git a/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/modAccessor/ModChecker.java b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/modAccessor/ModChecker.java new file mode 100644 index 000000000..970082aa6 --- /dev/null +++ b/cleanroom/src/main/java/com/seibel/distanthorizons/cleanroom/modAccessor/ModChecker.java @@ -0,0 +1,52 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 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.distanthorizons.cleanroom.modAccessor; + +import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.ModContainer; + +import java.io.File; +import java.util.Optional; +import java.util.stream.Stream; + +public class ModChecker implements IModChecker +{ + public static final ModChecker INSTANCE = new ModChecker(); + + @Override + public boolean isModLoaded(String modid) + { + return Loader.isModLoaded(modid); + } + + @Override + public File modLocation(String modid) + { + Stream foundStream = Loader.instance().getModList().stream().filter(x -> x.getModId().equals(modid)); + Optional container = foundStream.findFirst(); + if (!container.isPresent()) + { + throw new RuntimeException("Mod not found: " + modid); + } + return container.get().getSource(); + } + +} diff --git a/cleanroom/src/main/resources/distanthorizons.default.mixin.json b/cleanroom/src/main/resources/distanthorizons.default.mixin.json new file mode 100644 index 000000000..3a766233c --- /dev/null +++ b/cleanroom/src/main/resources/distanthorizons.default.mixin.json @@ -0,0 +1,17 @@ +{ + "required": true, + "package": "com.seibel.distanthorizons.cleanroom.mixins", + "compatibilityLevel": "JAVA_8", + "target": "@env(DEFAULT)", + "mixins": [], + "minVersion": "0.8.7", + "server": [ + "server.MixinEntityPlayerMP" + ], + "client": [ + "client.MixinEntityRenderer", + "client.MixinNetHandlerPlayClient", + "client.MixinOptionsScreen", + "client.MixinRenderGlobal" + ] +} \ No newline at end of file diff --git a/cleanroom/src/main/resources/distanthorizons.mod.mixin.json b/cleanroom/src/main/resources/distanthorizons.mod.mixin.json new file mode 100644 index 000000000..970fb1a67 --- /dev/null +++ b/cleanroom/src/main/resources/distanthorizons.mod.mixin.json @@ -0,0 +1,11 @@ +{ + "required": false, + "package": "com.seibel.distanthorizons.cleanroom.mixins.mod", + "compatibilityLevel": "JAVA_8", + "target": "@env(MOD)", + "mixins": [], + "minVersion": "0.8.7", + "plugin": "com.seibel.distanthorizons.cleanroom.DistantHorizonsConfigPlugin", + "client": [ + ] +} \ No newline at end of file diff --git a/cleanroom/src/main/resources/mcmod.info b/cleanroom/src/main/resources/mcmod.info new file mode 100644 index 000000000..e8757de68 --- /dev/null +++ b/cleanroom/src/main/resources/mcmod.info @@ -0,0 +1,12 @@ +[{ + "modid": "${mod_id}", + "name": "${mod_name}", + "version": "${version}", + "mcversion": "1.12.2", + "description": "${description}", + "authorList": ["${cleanroom_authors}"], + "credits": "", + "url": "", + "updateJSON": "", + "logoFile": "${logo_path}" +}] \ No newline at end of file diff --git a/cleanroom/src/main/resources/pack.mcmeta b/cleanroom/src/main/resources/pack.mcmeta new file mode 100644 index 000000000..daa17a8dc --- /dev/null +++ b/cleanroom/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "${mod_name} Resources", + "pack_format": 3 + } +} \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java b/common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java index 4ebc2491a..17bec1ddc 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java @@ -1,6 +1,5 @@ package com.seibel.distanthorizons.common; -import com.mojang.brigadier.CommandDispatcher; import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent; @@ -30,7 +29,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccesso import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.ModInfo; -import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; import com.seibel.distanthorizons.core.logging.DhLogger; @@ -39,6 +37,11 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Supplier; +#if MC_VER > MC_1_12_2 +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandSourceStack; +#endif + /** * Base for all mod loader initializers * and handles most setup. @@ -62,7 +65,9 @@ public abstract class AbstractModInitializer protected abstract IEventProxy createServerProxy(boolean isDedicated); protected abstract void initializeModCompat(); + #if MC_VER > MC_1_12_2 protected abstract void subscribeRegisterCommandsEvent(Consumer> eventHandler); + #endif protected abstract void subscribeClientStartedEvent(Runnable eventHandler); protected abstract void subscribeServerStartingEvent(Consumer eventHandler); @@ -130,8 +135,10 @@ public abstract class AbstractModInitializer this.initializeModCompat(); LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers..."); + #if MC_VER > MC_1_12_2 this.commandInitializer = new CommandInitializer(); this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer.initCommands(dispatcher); }); + #endif this.subscribeServerStartingEvent(server -> { @@ -141,11 +148,20 @@ public abstract class AbstractModInitializer Initializer.postConfigInit(); this.postInit(); this.postServerInit(); + #if MC_VER > MC_1_12_2 this.commandInitializer.onServerReady(); + #endif this.checkForUpdates(); - LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory()); + String serverFolderPath; + #if MC_VER <= MC_1_12_2 + serverFolderPath = server.getDataDirectory() + ""; + #else + serverFolderPath = server.getServerDirectory() + ""; + #endif + + LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + serverFolderPath); }); } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java b/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java index dd2b400dc..a4b5d6235 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/AbstractPluginPacketSender.java @@ -12,10 +12,17 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSende import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import io.netty.buffer.ByteBufUtil; +#if MC_VER <= MC_1_12_2 +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; +#else import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; +#endif -#if MC_VER <= MC_1_21_10 +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.ResourceLocation; +#elif MC_VER <= MC_1_21_10 import net.minecraft.resources.ResourceLocation; #else import net.minecraft.resources.Identifier; @@ -30,7 +37,9 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender .fileLevelConfig(Config.Common.Logging.logNetworkEventToFile) .build(); - #if MC_VER <= MC_1_20_6 + #if MC_VER <= MC_1_12_2 + public static final String WRAPPER_PACKET_RESOURCE = "channelDH"; // resource_namespace + packet_path > 20 characters + #elif MC_VER <= MC_1_20_6 public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); #elif MC_VER <= MC_1_21_10 public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); @@ -52,14 +61,14 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender @Override public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message) { - this.sendToClient((ServerPlayer) serverPlayer.getWrappedMcObject(), message); + this.sendToClient(#if MC_VER <= MC_1_12_2 (EntityPlayerMP) #else (ServerPlayer) #endif serverPlayer.getWrappedMcObject(), message); } - public abstract void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message); + public abstract void sendToClient(#if MC_VER <= MC_1_12_2 EntityPlayerMP #else ServerPlayer #endif serverPlayer, AbstractNetworkMessage message); @Override public abstract void sendToServer(AbstractNetworkMessage message); - public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in) + public AbstractNetworkMessage decodeMessage(#if MC_VER <= MC_1_12_2 PacketBuffer #else FriendlyByteBuf #endif in) { AbstractNetworkMessage message = null; @@ -100,7 +109,7 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender } } - public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message) + public void encodeMessage(#if MC_VER <= MC_1_12_2 PacketBuffer #else FriendlyByteBuf #endif out, AbstractNetworkMessage message) { // This is intentionally unhandled, because errors related to this are unlikely to appear in wild Objects.requireNonNull(message); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commands/AbstractCommand.java b/common/src/main/java/com/seibel/distanthorizons/common/commands/AbstractCommand.java index 01e177ef2..4e8d38eb0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commands/AbstractCommand.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commands/AbstractCommand.java @@ -1,5 +1,9 @@ package com.seibel.distanthorizons.common.commands; +#if MC_VER <= MC_1_12_2 +public abstract class AbstractCommand {} + +#else import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper; @@ -100,3 +104,4 @@ public abstract class AbstractCommand } } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commands/CommandInitializer.java b/common/src/main/java/com/seibel/distanthorizons/common/commands/CommandInitializer.java index dc29975a9..ba0456a32 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commands/CommandInitializer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commands/CommandInitializer.java @@ -1,12 +1,26 @@ package com.seibel.distanthorizons.common.commands; - +#if MC_VER <= MC_1_12_2 +import com.seibel.distanthorizons.core.config.ConfigHandler; +import com.seibel.distanthorizons.core.config.types.AbstractConfigBase; +import com.seibel.distanthorizons.core.config.types.ConfigEntry; +import com.seibel.distanthorizons.core.logging.f3.F3Screen; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.text.TextComponentString; +#else import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.commands.CommandSourceStack; +import static net.minecraft.commands.Commands.literal; +#endif import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE; -import static net.minecraft.commands.Commands.literal; #if MC_VER <= MC_1_21_10 #else @@ -25,6 +39,70 @@ public class CommandInitializer #endif + + #if MC_VER <= MC_1_12_2 + public static ICommand initCommands() + { + return new CommandBase() + { + @Override + public String getName() { return "dh"; } + + @Override + public String getUsage(ICommandSender sender) { return "/dh "; } + + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) + { + if (args.length == 0) + { + if (DEBUG_CODEC_CRASH_MESSAGE) + { + sender.sendMessage(new TextComponentString("Usage: /dh ")); + } + else + { + sender.sendMessage(new TextComponentString("Usage: /dh configEntry, String value) + { + Class type = configEntry.getType(); + + if (type == Boolean.class) ((ConfigEntry) configEntry).set(Boolean.parseBoolean(value)); + else if (type == Integer.class) ((ConfigEntry) configEntry).set(Integer.parseInt(value)); + else if (type == Double.class) ((ConfigEntry) configEntry).set(Double.parseDouble(value)); + else if (type == Float.class) ((ConfigEntry) configEntry).set(Float.parseFloat(value)); + else if (type == Long.class) ((ConfigEntry) configEntry).set(Long.parseLong(value)); + else if (type == String.class) ((ConfigEntry) configEntry).set(value); + else if (type.isEnum()) ((ConfigEntry) configEntry).set(Enum.valueOf((Class) type, value)); + else throw new RuntimeException("Unsupported config type: " + type.getSimpleName()); + } + public void execute(ICommandSender sender, String[] args) + { + if (args.length < 2) + { + sender.sendMessage(new TextComponentString("Usage: /dh config [value]")); + return; + } + + String configName = args[1]; + AbstractConfigBase found = null; + for (AbstractConfigBase entry : ConfigHandler.INSTANCE.configBaseList) + { + if (entry instanceof ConfigEntry && configName.equals(((ConfigEntry) entry).getChatCommandName())) + { + found = entry; + break; + } + } + + if (found == null) + { + sender.sendMessage(new TextComponentString("Unknown config: " + configName)); + return; + } + + ConfigEntry configEntry = (ConfigEntry) found; + if (args.length == 2) + { + sender.sendMessage(new TextComponentString("Current value of " + configName + " is " + configEntry.get())); + } + else + { + String value = args[2]; + try + { + setConfigValue(configEntry, value); + sender.sendMessage(new TextComponentString("Changed " + configName + " to " + value)); + } + catch (Exception e) + { + sender.sendMessage(new TextComponentString("Invalid value: " + value)); + } + } + } + + #else + private static final List> commandArguments = Arrays.asList( new CommandArgumentData<>(Integer.class, configEntry -> integer(configEntry.getMin(), configEntry.getMax()), IntegerArgumentType::getInteger), new CommandArgumentData<>(Double.class, configEntry -> doubleArg(configEntry.getMin(), configEntry.getMax()), DoubleArgumentType::getDouble), @@ -150,5 +221,6 @@ public class ConfigCommand extends AbstractCommand } } + #endif -} \ No newline at end of file +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commands/CrashCommand.java b/common/src/main/java/com/seibel/distanthorizons/common/commands/CrashCommand.java index 7c6f09d71..5b9fd17d2 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commands/CrashCommand.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commands/CrashCommand.java @@ -1,15 +1,60 @@ package com.seibel.distanthorizons.common.commands; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerState; import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage; + +#if MC_VER <= MC_1_12_2 +import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.text.TextComponentString; +#else import net.minecraft.commands.CommandSourceStack; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import static net.minecraft.commands.Commands.literal; +#endif + public class CrashCommand extends AbstractCommand { + #if MC_VER <= MC_1_12_2 + public void execute(ICommandSender sender, String[] args) + { + if (!(sender instanceof EntityPlayerMP)) + { + sender.sendMessage(new TextComponentString("This command can only be run by a player")); + return; + } + + if (args.length < 2) + { + sender.sendMessage(new TextComponentString("Usage: /dh crash ")); + return; + } + + if (SharedApi.tryGetDhServerWorld() == null) return; + + ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld() + .getServerPlayerStateManager() + .getConnectedPlayer(ServerPlayerWrapper.getWrapper((EntityPlayerMP) sender)); + + if (serverPlayerState == null) return; + + switch (args[1]) + { + case "encode": + serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE)); + break; + case "decode": + serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE)); + break; + default: + sender.sendMessage(new TextComponentString("Usage: /dh crash ")); + } + } + #else @Override public LiteralArgumentBuilder buildCommand() { @@ -40,5 +85,6 @@ public class CrashCommand extends AbstractCommand return 1; })); } + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commands/DebugCommand.java b/common/src/main/java/com/seibel/distanthorizons/common/commands/DebugCommand.java index 88b1c8311..77a21d783 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commands/DebugCommand.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commands/DebugCommand.java @@ -1,25 +1,44 @@ package com.seibel.distanthorizons.common.commands; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; + +#if MC_VER <= MC_1_12_2 +import net.minecraft.command.ICommandSender; +import net.minecraft.util.text.TextComponentString; +#else +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.commands.CommandSourceStack; +import static net.minecraft.commands.Commands.literal; +#endif + import java.util.ArrayList; import java.util.List; -import static net.minecraft.commands.Commands.literal; public class DebugCommand extends AbstractCommand { + private static String getDebugString() + { + List lines = new ArrayList<>(); + F3Screen.addStringToDisplay(lines); + return String.join("\n", lines); + } + + #if MC_VER > MC_1_12_2 @Override public LiteralArgumentBuilder buildCommand() { - return literal("debug") - .executes(c -> { - List lines = new ArrayList<>(); - F3Screen.addStringToDisplay(lines); - return this.sendSuccessResponse(c, String.join("\n", lines), false); - }); + return literal("debug") + .executes(c -> { + return this.sendSuccessResponse(c, getDebugString(), false); + }); } + #else + public void execute(ICommandSender sender) + { + sender.sendMessage(new TextComponentString(getDebugString())); + } + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commands/PregenCommand.java b/common/src/main/java/com/seibel/distanthorizons/common/commands/PregenCommand.java index 3cb0a88de..367b9d1be 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commands/PregenCommand.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commands/PregenCommand.java @@ -1,27 +1,36 @@ package com.seibel.distanthorizons.common.commands; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.generation.PregenManager; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D; import com.seibel.distanthorizons.core.world.DhServerWorld; + +#if MC_VER <= MC_1_12_2 +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.world.WorldServer; +#else +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.coordinates.ColumnPosArgument; import net.minecraft.server.level.ColumnPos; import net.minecraft.server.level.ServerLevel; -import java.util.Objects; -import java.util.concurrent.CancellationException; -import java.util.concurrent.CompletableFuture; - import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static net.minecraft.commands.Commands.argument; import static net.minecraft.commands.Commands.literal; +#endif + +import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; + public class PregenCommand extends AbstractCommand { @@ -31,6 +40,101 @@ public class PregenCommand extends AbstractCommand return world.getPregenManager(); } + #if MC_VER <= MC_1_12_2 + public void execute(MinecraftServer server, ICommandSender sender, String[] args) + { + if (args.length < 2) + { + sender.sendMessage(new TextComponentString("Usage: /dh pregen ")); + return; + } + + switch (args[1]) + { + case "status": + { + String statusString = this.getPregenManager().getStatusString(); + sender.sendMessage(new TextComponentString( + statusString != null ? statusString : "Pregen is not running")); + break; + } + case "start": + { + if (args.length < 5) + { + sender.sendMessage(new TextComponentString("Usage: /dh pregen start ")); + return; + } + + try + { + String dimensionName = args[2]; + int x = Integer.parseInt(args[3]); + int z = Integer.parseInt(args[4]); + int chunkRadius = args.length >= 6 ? Integer.parseInt(args[5]) : 32; + + // find the world by dimension name + WorldServer world = null; + for (WorldServer w : server.worlds) + { + if (w.provider.getDimensionType().getName().equals(dimensionName)) + { + world = w; + break; + } + } + + if (world == null) + { + sender.sendMessage(new TextComponentString("Unknown dimension: " + dimensionName)); + return; + } + + sender.sendMessage(new TextComponentString("Starting pregen. Progress will be in the server console.")); + + final ICommandSender finalSender = sender; + CompletableFuture future = this.getPregenManager().startPregen( + ServerLevelWrapper.getWrapper(world), + new DhBlockPos2D(x, z), + chunkRadius + ); + + future.whenComplete((result, throwable) -> { + if (throwable instanceof CancellationException) + { + finalSender.sendMessage(new TextComponentString("Pregen is cancelled")); + return; + } + else if (throwable != null) + { + finalSender.sendMessage(new TextComponentString("Pregen failed: " + throwable.getMessage())); + return; + } + finalSender.sendMessage(new TextComponentString("Pregen is complete")); + }); + } + catch (NumberFormatException e) + { + sender.sendMessage(new TextComponentString("Invalid number format")); + } + break; + } + case "stop": + { + CompletableFuture runningPregen = this.getPregenManager().getRunningPregen(); + if (runningPregen == null) + { + sender.sendMessage(new TextComponentString("Pregen is not running")); + return; + } + runningPregen.cancel(true); + break; + } + default: + sender.sendMessage(new TextComponentString("Unknown subcommand: " + args[1])); + } + } + #else @Override public LiteralArgumentBuilder buildCommand() { @@ -110,5 +214,5 @@ public class PregenCommand extends AbstractCommand runningPregen.cancel(true); return 1; } - + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/DhUpdateScreenBase.java b/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/DhUpdateScreenBase.java index e40507521..98293d7c3 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/DhUpdateScreenBase.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/DhUpdateScreenBase.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.common.commonMixins; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch; import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen; import com.seibel.distanthorizons.core.config.Config; @@ -11,16 +12,18 @@ import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.TitleScreen; +#if MC_VER <= MC_1_12_2 +#else +import net.minecraft.client.gui.screens.TitleScreen; +#endif import java.util.ArrayList; public class DhUpdateScreenBase { private static final DhLogger LOGGER = new DhLoggerBuilder().build(); - private static final Minecraft MC = Minecraft.getInstance(); - + private static final Minecraft MC = Minecraft #if MC_VER <= MC_1_12_2 .getMinecraft() #else .getInstance() #endif; public static void tryShowUpdateScreenAndRunAutoUpdateStartup(Runnable runnable) @@ -86,3 +89,4 @@ public class DhUpdateScreenBase } } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinChunkMapCommon.java b/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinChunkMapCommon.java index 4f04819d0..b72886fb4 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinChunkMapCommon.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinChunkMapCommon.java @@ -6,15 +6,23 @@ import com.seibel.distanthorizons.core.api.internal.ServerApi; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; +#else import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; +#endif import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class MixinChunkMapCommon { - + #if MC_VER <= MC_1_12_2 + public static void onChunkSave(WorldServer level, Chunk chunk) + #else public static void onChunkSave(ServerLevel level, ChunkAccess chunk, CallbackInfoReturnable ci) + #endif { IServerLevelWrapper levelWrapper = ServerLevelWrapper.getWrapper(level); @@ -37,7 +45,7 @@ public class MixinChunkMapCommon // is this chunk being saved to disk? - boolean savingChunkToDisk = ci.getReturnValue(); + boolean savingChunkToDisk = #if MC_VER <= MC_1_12_2 true #else ci.getReturnValue() #endif; // true means a chunk was saved to disk if (!savingChunkToDisk) { @@ -50,7 +58,12 @@ public class MixinChunkMapCommon // MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks) // this logic should prevent that from happening - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + if (!chunk.isTerrainPopulated() || !chunk.isLightPopulated()) + { + return; + } + #elif MC_VER <= MC_1_17_1 if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect()) { return; @@ -67,7 +80,12 @@ public class MixinChunkMapCommon // biome validation // // some chunks may be missing their biomes, which cause issues when attempting to save them - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + if (chunk. getBiomeArray() == null) + { + return; + } + #elif MC_VER <= MC_1_17_1 if (chunk.getBiomes() == null) { return; diff --git a/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinVanillaFogCommon.java b/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinVanillaFogCommon.java index ee90f8499..e198607f9 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinVanillaFogCommon.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinVanillaFogCommon.java @@ -12,11 +12,18 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; +#if MC_VER <= MC_1_12_2 +#else +import net.minecraft.client.Camera; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +#endif -#if MC_VER < MC_1_17_1 +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.MobEffects; +#elif MC_VER < MC_1_17_1 import net.minecraft.world.level.material.FluidState; import net.minecraft.client.renderer.FogRenderer; import net.minecraft.client.renderer.FogRenderer.FogMode; @@ -57,16 +64,18 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; public class MixinVanillaFogCommon { - - #if MC_VER < MC_1_21_6 + #if MC_VER <= MC_1_12_2 + public static boolean cancelFog(int startCoords, Minecraft mc) + #elif MC_VER < MC_1_21_6 public static boolean cancelFog(Camera camera, FogRenderer.FogMode fogMode) #else public static boolean cancelFog() #endif { - - #if MC_VER < MC_1_21_6 + #if MC_VER <= MC_1_12_2 + EntityPlayerSP entity = mc.player; + #elif MC_VER < MC_1_21_6 Entity entity = camera.getEntity(); #elif MC_VER <= MC_1_21_10 Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera(); @@ -76,13 +85,23 @@ public class MixinVanillaFogCommon Entity entity = camera.entity(); #endif - + #if MC_VER <= MC_1_12_2 + boolean cameraNotInFluid = cameraNotInFluid(mc); + #else boolean cameraNotInFluid = cameraNotInFluid(camera); + #endif + + #if MC_VER <= MC_1_12_2 + boolean isSpecialFog = entity.isPotionActive(MobEffects.BLINDNESS); + #else boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS); + #endif boolean cancelFog = !isSpecialFog; cancelFog = cancelFog && cameraNotInFluid; - #if MC_VER < MC_1_21_6 + #if MC_VER <= MC_1_12_2 + cancelFog = cancelFog && startCoords == 0; // 0 = terrain fog + #elif MC_VER < MC_1_21_6 cancelFog = cancelFog && (fogMode == FogRenderer.FogMode.FOG_TERRAIN); #endif @@ -100,10 +119,15 @@ public class MixinVanillaFogCommon return cancelFog; } - + #if MC_VER <= MC_1_12_2 + private static boolean cameraNotInFluid(Minecraft mc) + #else private static boolean cameraNotInFluid(Camera camera) + #endif { - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + boolean cameraNotInFluid = mc.getRenderViewEntity() != null && !mc.world.getBlockState(mc.getRenderViewEntity().getPosition()).getMaterial().isLiquid(); + #elif MC_VER < MC_1_17_1 FluidState fluidState = camera.getFluidInCamera(); boolean cameraNotInFluid = fluidState.isEmpty(); #else diff --git a/common/src/main/java/com/seibel/distanthorizons/common/render/blaze/BlazeDhGenericObjectRenderer.java b/common/src/main/java/com/seibel/distanthorizons/common/render/blaze/BlazeDhGenericObjectRenderer.java index be403eaaa..fd92d28fe 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/render/blaze/BlazeDhGenericObjectRenderer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/render/blaze/BlazeDhGenericObjectRenderer.java @@ -57,6 +57,7 @@ import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.render.RenderParams; +import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler; import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer; import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup; @@ -615,5 +616,27 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer + //================// + // base overrides // + //================// + //region + + @Override + public void close() + { + // close is called outside the render thread and buffer closing must be done on the render thread + RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("Generic Obj Cleanup", () -> + { + if (this.vertUniformBuffer != null) + { + this.vertUniformBuffer.close(); + } + }); + } + + //endregion + + + } #endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/generic/GlGenericObjectRenderer.java b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/generic/GlGenericObjectRenderer.java index a6fbb61b1..5670cf08e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/generic/GlGenericObjectRenderer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/generic/GlGenericObjectRenderer.java @@ -748,4 +748,27 @@ public class GlGenericObjectRenderer implements IDhGenericRenderer + //================// + // base overrides // + //================// + //region + + @Override + public void close() + { + if (this.boxVertexBuffer != null) + { + this.boxVertexBuffer.close(); + } + + if (this.boxIndexBuffer != null) + { + this.boxIndexBuffer.close(); + } + } + + //endregion + + + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/GLState.java b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/GLState.java index 6107a7a24..b5f9bb355 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/GLState.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/GLState.java @@ -97,7 +97,9 @@ public class GLState implements AutoCloseable { this.frameBufferTexture0 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); this.frameBufferTexture1 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); - this.frameBufferDepthTexture = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); + + int depthType = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + this.frameBufferDepthTexture = (depthType == GL32.GL_TEXTURE) ? GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) : 0; } else { @@ -179,9 +181,21 @@ public class GLState implements AutoCloseable // attempting to set textures on the default frame buffer (ID 0) will throw errors if (frameBufferSet) { - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0); - GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0); + if (GL32.glIsTexture(this.frameBufferTexture0)) + { + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0); + } + + if (this.frameBufferTexture1 != 0 && GL32.glIsTexture(this.frameBufferTexture1)) + { + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0); + } + + if (GL32.glIsTexture(this.frameBufferDepthTexture)) + { + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0); + } + } GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLBuffer.java b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLBuffer.java index bcde6edbf..27aad3dc0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLBuffer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLBuffer.java @@ -23,11 +23,17 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper; import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.jar.EPlatform; import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.ThreadUtil; +import com.seibel.distanthorizons.core.util.objects.Pair; +import com.seibel.distanthorizons.core.util.objects.pooling.PhantomLoggingHelper; +import com.seibel.distanthorizons.coreapi.ModInfo; +import com.seibel.distanthorizons.coreapi.util.StringUtil; import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL44; @@ -35,6 +41,8 @@ import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicInteger; @@ -50,14 +58,35 @@ public class GLBuffer implements AutoCloseable private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE; + // TODO move to a shared location that can be handled by both GL and Blaze3D buffers + /** if enabled the number of GC'ed buffers will be logged */ + private static final boolean LOG_PHANTOM_RECOVERY = ModInfo.IS_DEV_BUILD; + /** If enabled buffers allocation/upload stacks will be logged when GC'ed. */ + private static final boolean LOG_PHANTOM_ALLOCATION_STACKS = false; // disabled by default due to the increased GC load + public static final double BUFFER_EXPANSION_MULTIPLIER = 1.3; public static final double BUFFER_SHRINK_TRIGGER = BUFFER_EXPANSION_MULTIPLIER * BUFFER_EXPANSION_MULTIPLIER; + + /** + * On macOS the legacy OpenGL -> Metal bridge crashes with SIGBUS in + * {@code _platform_memmove} when {@code glBufferData} or {@code glBufferSubData} + * are called with a large ByteBuffer in one shot. To work around it, we split + * the upload into smaller sub-data calls that each fit comfortably inside the + * driver's internal staging path.
+ * 256 KiB tuned empirically against macOS 26.5 — a 1 MiB chunk still + * tripped the same {@code _platform_memmove} crash inside + * {@code glBufferSubData_Exec}, but 256 KiB consistently survives. + */ + public static final int MAC_UPLOAD_CHUNK_BYTES = 256 * 1024; + /** Threshold above which the chunked path kicks in on macOS. */ + public static final int MAC_UPLOAD_CHUNK_THRESHOLD = MAC_UPLOAD_CHUNK_BYTES; /** the number of active buffers, can be used for debugging */ public static AtomicInteger bufferCount = new AtomicInteger(0); private static final int PHANTOM_REF_CHECK_TIME_IN_MS = 5 * 1000; private static final ConcurrentHashMap, Integer> PHANTOM_TO_BUFFER_ID = new ConcurrentHashMap<>(); private static final ConcurrentHashMap> BUFFER_ID_TO_PHANTOM = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap BUFFER_ID_TO_ALLOCATION_STRING = new ConcurrentHashMap<>(); private static final ReferenceQueue PHANTOM_REFERENCE_QUEUE = new ReferenceQueue<>(); private static final ThreadPoolExecutor CLEANUP_THREAD = ThreadUtil.makeSingleDaemonThreadPool("GLBuffer Cleanup"); @@ -128,8 +157,9 @@ public class GLBuffer implements AutoCloseable long writeStamp = renderStampLock.writeLock(); try { - int oldId = this.id; + final int oldId = this.id; this.id = GLMC.glGenBuffers(); + //LOGGER.info("created [" + newId + "]."); // destroy the old buffer // after the new one has been created @@ -139,7 +169,7 @@ public class GLBuffer implements AutoCloseable { // this ID doesn't need to be tracked anymore tryRemoveBufferIdFromPhantom(oldId); - destroyBufferIdNow(oldId); + destroyBufferIdNow(oldId, "destroyOldAndCreate"); } @@ -149,6 +179,8 @@ public class GLBuffer implements AutoCloseable PhantomReference phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE); PHANTOM_TO_BUFFER_ID.put(phantom, this.id); BUFFER_ID_TO_PHANTOM.put(this.id, phantom); + + this.updateAllocationStackTrace(); } finally { @@ -181,7 +213,8 @@ public class GLBuffer implements AutoCloseable this.id = 0; this.size = 0; - RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); }); + //LOGGER.info("async destroy [" + idToDelete + "]."); + RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete, "destroyAsync"); }); } finally { @@ -189,49 +222,43 @@ public class GLBuffer implements AutoCloseable } } - private static void destroyBufferIdNow(int id) + private static void destroyBufferIdNow(int id, String cause) { // only delete valid buffers if (id == 0) { - LOGGER.warn("Attempted to destroy a buffer with ID 0, VRAM memory leaks may occur."); + LOGGER.warn("Attempted to destroy a buffer with ID 0, VRAM memory leaks may occur, cause: ["+cause+"]."); return; } bufferCount.decrementAndGet(); + GLMC.glDeleteBuffers(id); - // destroy the buffer if it exists, - // the buffer may not exist if the destroy method is called twice - if (GL32.glIsBuffer(id)) + if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get()) { - GLMC.glDeleteBuffers(id); - - if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get()) - { - LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]"); - } - } - else - { - // shouldn't happen, but just in case - LOGGER.warn("Attempted to destroy a non buffer object with ID ["+id+"]."); + LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "], cause: ["+cause+"]."); } } /** should be called before {@link GLBuffer#destroyBufferIdNow} */ private static void tryRemoveBufferIdFromPhantom(int id) { - if (BUFFER_ID_TO_PHANTOM.containsKey(id)) + // will contain nothing if stack tracking isn't enabled + BUFFER_ID_TO_ALLOCATION_STRING.remove(id); + + PhantomReference phantom = BUFFER_ID_TO_PHANTOM.remove(id); + if (phantom != null) { - Reference phantom = BUFFER_ID_TO_PHANTOM.get(id); - // if we are manually closing this buffer, we don't want the phantom reference to accidentally close it again // this can cause a race condition were we accidentally delete an in-use buffer and cause NVIDIA // to throw an EXCEPTION_ACCESS_VIOLATION when we attempt to render it phantom.clear(); - PHANTOM_TO_BUFFER_ID.remove(phantom); - BUFFER_ID_TO_PHANTOM.remove(id); + Integer phantomId = PHANTOM_TO_BUFFER_ID.remove(phantom); + if (phantomId == null) + { + LOGGER.warn("No Phantom->ID binding stored for ID ["+id+"]"); + } } else { @@ -322,8 +349,25 @@ public class GLBuffer implements AutoCloseable LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use bufferData upload method!"); int bbSize = bb.limit() - bb.position(); - GL32.glBufferData(this.getBufferBindingTarget(), bb, bufferDataHint); + int target = this.getBufferBindingTarget(); + + if (shouldUploadToGpuInChunks(bbSize)) + { + // Two-step path used on macOS to dodge the Apple OpenGL -> Metal + // memmove SIGBUS triggered by uploading a large ByteBuffer in one + // glBufferData call: + // 1) allocate-only with the size overload (no memcpy) + // 2) fill the buffer through chunked glBufferSubData calls + GL32.glBufferData(target, (long) bbSize, bufferDataHint); + subDataUploadInChunks(target, 0, bb, MAC_UPLOAD_CHUNK_BYTES); + } + else + { + GL32.glBufferData(target, bb, bufferDataHint); + } this.size = bbSize; + + this.updateAllocationStackTrace(); } /** Requires the buffer to be bound */ protected void uploadSubData(ByteBuffer bb, int maxExpansionSize, int bufferDataHint) @@ -331,14 +375,30 @@ public class GLBuffer implements AutoCloseable LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use subData upload method!"); int bbSize = bb.limit() - bb.position(); + int target = this.getBufferBindingTarget(); if (this.size < bbSize || this.size > bbSize * BUFFER_SHRINK_TRIGGER) { int newSize = (int) (bbSize * BUFFER_EXPANSION_MULTIPLIER); - if (newSize > maxExpansionSize) newSize = maxExpansionSize; - GL32.glBufferData(this.getBufferBindingTarget(), newSize, bufferDataHint); + if (newSize > maxExpansionSize) + { + newSize = maxExpansionSize; + } + + // allocate-only — no memcpy, safe on macOS regardless of size + GL32.glBufferData(target, (long) newSize, bufferDataHint); this.size = newSize; } - GL32.glBufferSubData(this.getBufferBindingTarget(), 0, bb); + + if (shouldUploadToGpuInChunks(bbSize)) + { + subDataUploadInChunks(target, 0, bb, MAC_UPLOAD_CHUNK_BYTES); + } + else + { + GL32.glBufferSubData(target, 0, bb); + } + + this.updateAllocationStackTrace(); } //endregion @@ -396,6 +456,91 @@ public class GLBuffer implements AutoCloseable } } + /** + * macOS-only mitigation for the SIGBUS in + * {@code libsystem_platform.dylib _platform_memmove} that happens when the + * Apple OpenGL -> Metal translation layer copies a single large ByteBuffer + * out of LWJGL into driver memory. Splitting the copy into + * {@link #MAC_UPLOAD_CHUNK_BYTES} slices keeps every memmove inside a size + * the bridge handles reliably. + */ + private static boolean shouldUploadToGpuInChunks(int byteCount) + { + return EPlatform.get() == EPlatform.MACOS + && byteCount > MAC_UPLOAD_CHUNK_THRESHOLD; + } + + /** + * Uploads {@code bb} into the currently bound buffer at {@code baseOffset} + * using a sequence of {@link GL32#glBufferSubData(int, long, ByteBuffer)} + * calls of at most {@code chunkBytes} each. The buffer's position/limit are + * restored before returning. + */ + private static void subDataUploadInChunks(int target, int baseOffset, ByteBuffer bb, int chunkBytes) + { + final int origPos = bb.position(); + final int origLimit = bb.limit(); + try + { + final int total = origLimit - origPos; + int uploaded = 0; + while (uploaded < total) + { + int chunk = Math.min(chunkBytes, total - uploaded); + bb.position(origPos + uploaded); + bb.limit(origPos + uploaded + chunk); + GL32.glBufferSubData(target, (long) (baseOffset + uploaded), bb); + uploaded += chunk; + // Force the driver to drain its command queue between chunks + // so the OpenGL -> Metal bridge processes (and frees) each + // staging copy before the next sub-data call piles another + // memmove on top of it. + if (uploaded < total) + { + GL32.glFlush(); + } + } + } + finally + { + bb.limit(origLimit); + bb.position(origPos); + } + } + + /** + * used to help track down leaks where the buffer isn't properly closed + * Note: this probably needs extending to accept a stack trace from outside where it's being called + * since it's often called on the render thread in an un-helpful location. + */ + public void updateAllocationStackTrace() + { + if (LOG_PHANTOM_ALLOCATION_STACKS) + { + String stack; + + RenderThreadTaskHandler.QueuedRunnable parentQueuedRunnable; + // if this is running on the render thread, try getting the render task's stack trace instead + // since it's a lot more helpful than wherever the render thread tasks themselves are being run from + if (RenderThreadTaskHandler.INSTANCE.isCurrentThread() + && (parentQueuedRunnable = RenderThreadTaskHandler.INSTANCE.getCurrentlyRunningTask()) != null + && parentQueuedRunnable.stackTrace != null) + { + // trim off the getStacktrace() and queueRunningOnRenderThread() methods + StackTraceElement[] trimmedElements = Arrays.copyOfRange(parentQueuedRunnable.stackTrace, 2, parentQueuedRunnable.stackTrace.length); + stack = StringUtil.join("\n", trimmedElements).intern(); + } + else + { + // not running on the render thread, use the normal stack trace + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + stack = StringUtil.join("\n", stackTraceElements).intern(); + } + + BUFFER_ID_TO_ALLOCATION_STRING.put(this.id, stack); + } + } + //endregion @@ -407,8 +552,13 @@ public class GLBuffer implements AutoCloseable private static void runPhantomReferenceCleanupLoop() { + // these arrays are stored here so they don't have to be re-allocated each loop + ArrayList> allocationStackTraceCountPairList = new ArrayList<>(); + while (true) { + allocationStackTraceCountPairList.clear(); + try { try @@ -417,20 +567,53 @@ public class GLBuffer implements AutoCloseable } catch (InterruptedException ignore) { } + int collectedCount = 0; Reference phantomRef = PHANTOM_REFERENCE_QUEUE.poll(); while (phantomRef != null) { // destroy the buffer if it hasn't been cleared yet - if (PHANTOM_TO_BUFFER_ID.containsKey(phantomRef)) + Integer idRef = PHANTOM_TO_BUFFER_ID.remove((PhantomReference)phantomRef); // cast to make IntelliJ happy + if (idRef != null) { - int id = PHANTOM_TO_BUFFER_ID.get(phantomRef); - RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer phantom destroy", () -> { destroyBufferIdNow(id); }); - //LOGGER.warn("Buffer Phantom collected, ID: ["+id+"]"); + BUFFER_ID_TO_PHANTOM.remove(idRef); + final int id = idRef; + RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer phantom destroy", () -> { destroyBufferIdNow(id, "runPhantomReferenceCleanupLoop"); }); + //LOGGER.info("Buffer Phantom collected, ID: ["+id+"]"); + + if (LOG_PHANTOM_ALLOCATION_STACKS) // stack trace shouldn't be null, but just in case + { + String stack = BUFFER_ID_TO_ALLOCATION_STRING.get(idRef); + PhantomLoggingHelper.putAndIncrementTrackingString(stack, allocationStackTraceCountPairList); + } + } + else + { + LOGGER.warn("Failed to find Buffer ID for phantom reference: ["+phantomRef+"]"); } + + collectedCount++; phantomRef = PHANTOM_REFERENCE_QUEUE.poll(); } + + + + if (LOG_PHANTOM_RECOVERY) + { + // we only want to log when something has been returned + if (collectedCount != 0) + { + LOGGER.warn("GLBuffer phantom recovered: ["+ F3Screen.NUMBER_FORMAT.format(collectedCount)+"]."); + + // log stack traces if present + if (LOG_PHANTOM_ALLOCATION_STACKS) + { + PhantomLoggingHelper.LogAllocationStackTracePairCounts(LOGGER, allocationStackTraceCountPairList); + } + } + } + } catch (Exception e) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLIndexBuffer.java b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLIndexBuffer.java index 56793aabb..0a8db0883 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLIndexBuffer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/render/openGl/glObject/buffer/GLIndexBuffer.java @@ -37,10 +37,11 @@ public class GLIndexBuffer extends GLBuffer protected int glType = GL32.GL_UNSIGNED_INT; public int getGlType() { return this.glType; } - public GLIndexBuffer(boolean isBufferStorage) - { - super(isBufferStorage); - } + + + public GLIndexBuffer(boolean isBufferStorage) { super(isBufferStorage); } + + @Override public void destroyAsync() diff --git a/common/src/main/java/com/seibel/distanthorizons/common/util/ProxyUtil.java b/common/src/main/java/com/seibel/distanthorizons/common/util/ProxyUtil.java index b603288b3..5af15153f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/util/ProxyUtil.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/util/ProxyUtil.java @@ -22,23 +22,34 @@ package com.seibel.distanthorizons.common.util; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +#else import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.LevelAccessor; - +#endif public class ProxyUtil { - public static ILevelWrapper getLevelWrapper(LevelAccessor level) + public static ILevelWrapper getLevelWrapper( + #if MC_VER <= MC_1_12_2 World #else LevelAccessor #endif level + ) { ILevelWrapper levelWrapper; - if (level instanceof ServerLevel) + if (level instanceof #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif) { - levelWrapper = ServerLevelWrapper.getWrapper((ServerLevel) level); + levelWrapper = ServerLevelWrapper.getWrapper( + #if MC_VER <= MC_1_12_2 (WorldServer) #else (ServerLevel) #endif level + ); } else { - levelWrapper = ClientLevelWrapper.getWrapper((ClientLevel) level); + levelWrapper = ClientLevelWrapper.getWrapper( + #if MC_VER <= MC_1_12_2 (WorldClient) #else (ClientLevel) #endif level + ); } return levelWrapper; diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java index cff8c85e7..aa08f77db 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java @@ -26,9 +26,15 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.util.math.Mat4f; +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +#else import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.ChunkPos; +#endif /** * This class converts to and from Minecraft objects (Ex: Matrix4f) @@ -47,7 +53,8 @@ public class McObjectConverter /** 4x4 float matrix converter */ public static Mat4f Convert( - #if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f + #if MC_VER <= MC_1_12_2 org.joml.Matrix4f + #elif MC_VER < MC_1_19_4 com.mojang.math.Matrix4f #elif MC_VER < MC_1_21_6 org.joml.Matrix4f #else org.joml.Matrix4fc #endif @@ -56,21 +63,24 @@ public class McObjectConverter FloatBuffer buffer = FloatBuffer.allocate(16); storeMatrix(mcMatrix, buffer); Mat4f matrix = new Mat4f(buffer); - #if MC_VER < MC_1_19_4 + #if MC_VER > MC_1_12_2 && MC_VER < MC_1_19_4 matrix.transpose(); // In 1.19.3 and later, we no longer need to transpose it #endif return matrix; } /** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */ private static void storeMatrix( - #if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f + #if MC_VER <= MC_1_12_2 org.joml.Matrix4f + #elif MC_VER < MC_1_19_4 com.mojang.math.Matrix4f #elif MC_VER < MC_1_21_6 org.joml.Matrix4f #else org.joml.Matrix4fc #endif matrix, FloatBuffer buffer) { - #if MC_VER < MC_1_19_4 + #if MC_VER <= MC_1_12_2 + matrix.get(buffer); + #elif MC_VER < MC_1_19_4 matrix.store(buffer); #else // Mojang starts to use joml's Matrix4f libary in 1.19.3 so we copy their store method and use it here if its newer than 1.19.3 @@ -94,35 +104,37 @@ public class McObjectConverter } - static final Direction[] directions; + static final #if MC_VER <= MC_1_12_2 EnumFacing[] #else Direction[] #endif directions; static final EDhDirection[] lodDirections; static { EDhDirection[] lodDirs = EDhDirection.values(); - directions = new Direction[lodDirs.length]; + + directions = new #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif[lodDirs.length]; + lodDirections = new EDhDirection[lodDirs.length]; for (EDhDirection lodDir : lodDirs) { - Direction dir; + #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif dir; switch (lodDir.name().toUpperCase()) { case "DOWN": - dir = Direction.DOWN; + dir = #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif.DOWN; break; case "UP": - dir = Direction.UP; + dir = #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif.UP; break; case "NORTH": - dir = Direction.NORTH; + dir = #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif.NORTH; break; case "SOUTH": - dir = Direction.SOUTH; + dir = #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif.SOUTH; break; case "WEST": - dir = Direction.WEST; + dir = #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif.WEST; break; case "EAST": - dir = Direction.EAST; + dir = #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif.EAST; break; default: dir = null; @@ -150,7 +162,7 @@ public class McObjectConverter #endif } - public static Direction Convert(EDhDirection lodDirection) { return directions[lodDirection.ordinal()]; } - public static EDhDirection Convert(Direction direction) { return lodDirections[direction.ordinal()]; } + public static #if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif Convert(EDhDirection lodDirection) { return directions[lodDirection.ordinal()]; } + public static EDhDirection Convert(#if MC_VER <= MC_1_12_2 EnumFacing #else Direction #endif direction) { return lodDirections[direction.ordinal()]; } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/VersionConstants.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/VersionConstants.java index f18c8db09..efd96f845 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/VersionConstants.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/VersionConstants.java @@ -51,7 +51,10 @@ public class VersionConstants implements IVersionConstants // it can't load client classes when running as a dedicated server, // which was how we were dynamically accessing the MC version string - #if MC_VER == MC_1_16_5 + #if MC_VER == MC_1_12_2 + return "1.12.2"; + + #elif MC_VER == MC_1_16_5 return "1.16.5"; #elif MC_VER == MC_1_17_1 diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java index 2dca01e27..8af7cb4fd 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java @@ -46,17 +46,30 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.IBatchGeneratorEnvironmentWrapper; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.client.multiplayer.ClientLevel; + #if MC_VER > MC_1_17_1 import net.minecraft.core.Holder; #endif + +#if MC_VER <= MC_1_12_2 +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +#else +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; +#endif import java.io.IOException; +import java.util.HashSet; /** * This handles creating abstract wrapper objects. @@ -84,7 +97,6 @@ public class WrapperFactory implements IWrapperFactory this.renderDefinition = SingletonInjector.INSTANCE.get(AbstractDhRenderApiDefinition.class); return this.renderDefinition; } - //endregion @@ -115,7 +127,7 @@ public class WrapperFactory implements IWrapperFactory throw new ClassCastException("levelWrapper must be returned by DH and of type ["+ILevelWrapper.class.getName()+"]."); } - return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); + return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); } @Override public IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException @@ -125,19 +137,19 @@ public class WrapperFactory implements IWrapperFactory throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"]."); } - return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); + return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); } @Override public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); } - @Override + @Override public IBiomeWrapper getPlainsBiomeWrapper(ILevelWrapper levelWrapper) { try { return BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, levelWrapper); } - catch (IOException e) + catch (IOException e) { throw new LodUtil.AssertFailureException("Unable to parse plains resource string ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], error:\n " + e.getMessage()); } @@ -192,25 +204,25 @@ public class WrapperFactory implements IWrapperFactory // correct number of parameters from the API // chunk - if (!(objectArray[0] instanceof ChunkAccess)) + if (!(objectArray[0] instanceof #if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif)) { throw new ClassCastException(createChunkWrapperErrorMessage(objectArray)); } - ChunkAccess chunk = (ChunkAccess) objectArray[0]; + #if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif chunk = (#if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif) objectArray[0]; // level / light source - if (!(objectArray[1] instanceof Level)) + if (!(objectArray[1] instanceof #if MC_VER <= MC_1_12_2 World #else Level #endif)) { throw new ClassCastException(createChunkWrapperErrorMessage(objectArray)); } // the level is needed for the DH level wrapper... - Level level = (Level) objectArray[1]; + #if MC_VER <= MC_1_12_2 World #else Level #endif level = (#if MC_VER <= MC_1_12_2 World #else Level #endif) objectArray[1]; // level wrapper - ILevelWrapper levelWrapper = level.isClientSide() - ? ClientLevelWrapper.getWrapper((ClientLevel)level) - : ServerLevelWrapper.getWrapper((ServerLevel)level); + ILevelWrapper levelWrapper = #if MC_VER <= MC_1_12_2 !level.isRemote #else level.isClientSide() #endif + ? ClientLevelWrapper.getWrapper((#if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif)level) + : ServerLevelWrapper.getWrapper((#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif)level); return new ChunkWrapper(chunk, levelWrapper); @@ -231,11 +243,11 @@ public class WrapperFactory implements IWrapperFactory String[] expectedClassNames; //#if MC_VER <= MC_1_XX_X - expectedClassNames = new String[] - { - ChunkAccess.class.getName(), - "[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing - }; + expectedClassNames = new String[] + { + #if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif.class.getName(), + "[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing + }; //#endif return createWrapperErrorMessage("Chunk wrapper", expectedClassNames, objectArray); @@ -258,7 +270,7 @@ public class WrapperFactory implements IWrapperFactory // documentation should be in the API interface - public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) + public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) { // confirm the API level wrapper is also a Core wrapper if (!(levelWrapper instanceof ILevelWrapper)) @@ -327,12 +339,12 @@ public class WrapperFactory implements IWrapperFactory { throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray)); } - if (!(objectArray[0] instanceof BlockState)) + if (!(objectArray[0] instanceof #if MC_VER <= MC_1_12_2 IBlockState #else BlockState #endif)) { throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray)); } - BlockState blockState = (BlockState) objectArray[0]; + #if MC_VER <= MC_1_12_2 IBlockState #else BlockState #endif blockState = (#if MC_VER <= MC_1_12_2 IBlockState #else BlockState #endif) objectArray[0]; return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper); //#endif } @@ -344,7 +356,7 @@ public class WrapperFactory implements IWrapperFactory { String[] expectedClassNames; - #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 + #if MC_VER <= MC_1_17_1 expectedClassNames = new String[] { Biome.class.getName() }; #else expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" }; @@ -367,8 +379,8 @@ public class WrapperFactory implements IWrapperFactory { // error header StringBuilder message = new StringBuilder( - wrapperName + " creation failed. \n" + - "Expected object array parameters: \n"); + wrapperName + " creation failed. \n" + + "Expected object array parameters: \n"); // expected parameters diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/AbstractDhTintGetter.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/AbstractDhTintGetter.java index cbf9c6529..e6361fb32 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/AbstractDhTintGetter.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/AbstractDhTintGetter.java @@ -1,5 +1,5 @@ package com.seibel.distanthorizons.common.wrappers.block; - +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.BlockBiomeWrapperPair; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; @@ -11,10 +11,14 @@ import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import net.minecraft.client.Minecraft; +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.biome.Biome; +#else import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.world.level.ColorResolver; import net.minecraft.world.level.biome.Biome; +#endif import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; @@ -45,8 +49,6 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter #endif private static final ConcurrentHashMap COLOR_BY_BLOCK_BIOME_PAIR = new ConcurrentHashMap<>(); - /** returned if the color cache is incomplete */ - public static final int INVALID_COLOR = -1; protected BiomeWrapper biomeWrapper; @@ -98,7 +100,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter * Can be called by DH directly, skipping some of MC's logic * to speed up tint getting slightly. * - * @return {@link AbstractDhTintGetter#INVALID_COLOR} if any of the biomes needed for this position + * @return {@link ClientBlockStateColorCache#INVALID_COLOR} if any of the biomes needed for this position * were not cached. In that case calling {@link AbstractDhTintGetter#getBlockTint(BlockPos, ColorResolver)} * will need to be called by MC's ColorResolver so we can * populate the color cache. @@ -159,9 +161,9 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter int id = FullDataPointUtil.getId(dataPoint); BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id); int color = this.tryGetClientBiomeColor(colorResolver, biomeWrapper); - if (color == INVALID_COLOR) + if (color == ClientBlockStateColorCache.INVALID_COLOR) { - return INVALID_COLOR; + return ClientBlockStateColorCache.INVALID_COLOR; } @@ -210,7 +212,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter // no color resolver is present, // the cache needs to be populated before // we can use the fast path - return INVALID_COLOR; + return ClientBlockStateColorCache.INVALID_COLOR; } @@ -363,3 +365,4 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java index 0d557f2df..68b06278d 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BiomeWrapper.java @@ -28,12 +28,15 @@ import java.util.concurrent.ConcurrentMap; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -import net.minecraft.world.level.Level; import com.seibel.distanthorizons.core.logging.DhLogger; - import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; -#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 +#if MC_VER > MC_1_12_2 +import net.minecraft.world.level.Level; +#endif + +#if MC_VER <= MC_1_12_2 +#elif MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 import net.minecraft.core.Registry; #elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2 import net.minecraft.core.Holder; @@ -45,14 +48,21 @@ import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; #endif -#if MC_VER <= MC_1_21_10 +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.ResourceLocation; +#elif MC_VER <= MC_1_21_10 import net.minecraft.resources.ResourceLocation; #else import net.minecraft.resources.Identifier; import net.minecraft.core.component.DataComponentMap; #endif +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.biome.Biome; +#else import net.minecraft.world.level.biome.Biome; +#endif + #if MC_VER >= MC_1_18_2 import net.minecraft.world.level.biome.Biomes; @@ -108,8 +118,13 @@ public class BiomeWrapper implements IBiomeWrapper //==============// // constructors // //==============// + //region - public static BiomeWrapper getBiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder #endif biome, ILevelWrapper levelWrapper) + #if MC_VER < MC_1_18_2 + public static BiomeWrapper getBiomeWrapper(Biome biome, ILevelWrapper levelWrapper) + #else + public static BiomeWrapper getBiomeWrapper(Holder biome, ILevelWrapper levelWrapper) + #endif { if (biome == null) { @@ -129,7 +144,12 @@ public class BiomeWrapper implements IBiomeWrapper return newWrapper; } } - private BiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder #endif biome, ILevelWrapper levelWrapper) + + #if MC_VER < MC_1_18_2 + private BiomeWrapper(Biome biome, ILevelWrapper levelWrapper) + #else + private BiomeWrapper(Holder biome, ILevelWrapper levelWrapper) + #endif { this.biome = biome; this.serialString = this.serialize(levelWrapper); @@ -138,11 +158,14 @@ public class BiomeWrapper implements IBiomeWrapper //LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]"); } + //endregion + //=========// // methods // //=========// + //region @Override public String getName() @@ -188,11 +211,14 @@ public class BiomeWrapper implements IBiomeWrapper @Override public String toString() { return this.getSerialString(); } + //endregion + //=======================// // serialization methods // //=======================// + //region public String serialize(ILevelWrapper levelWrapper) { @@ -219,8 +245,10 @@ public class BiomeWrapper implements IBiomeWrapper // generate the serial string // + #if MC_VER > MC_1_12_2 Level level = (Level)levelWrapper.getWrappedMcObject(); net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); + #endif #if MC_VER <= MC_1_21_10 ResourceLocation resourceLocation; @@ -228,7 +256,9 @@ public class BiomeWrapper implements IBiomeWrapper Identifier resourceLocation; #endif - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + resourceLocation = biome.getRegistryName(); + #elif MC_VER <= MC_1_17_1 resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome); #elif MC_VER <= MC_1_19_2 resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value()); @@ -293,11 +323,16 @@ public class BiomeWrapper implements IBiomeWrapper { try { + #if MC_VER > MC_1_12_2 Level level = (Level) levelWrapper.getWrappedMcObject(); net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); - + #endif + + #if MC_VER <= MC_1_12_2 + BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString); + #else BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess); - + #endif if (!deserializeResult.success) @@ -325,7 +360,11 @@ public class BiomeWrapper implements IBiomeWrapper } } + #if MC_VER <= MC_1_12_2 + public static BiomeDeserializeResult deserializeBiome(String resourceLocationString) throws IOException + #else public static BiomeDeserializeResult deserializeBiome(String resourceLocationString, net.minecraft.core.RegistryAccess registryAccess) throws IOException + #endif { // parse the resource location int separatorIndex = resourceLocationString.indexOf(":"); @@ -356,7 +395,10 @@ public class BiomeWrapper implements IBiomeWrapper boolean success; - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + Biome biome = Biome.REGISTRY.getObject(resourceLocation); + success = (biome != null); + #elif MC_VER <= MC_1_17_1 Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); success = (biome != null); #elif MC_VER <= MC_1_19_2 @@ -400,10 +442,14 @@ public class BiomeWrapper implements IBiomeWrapper return new BiomeDeserializeResult(success, biome); } + //endregion + + //================// // helper classes // //================// + //region public static class BiomeDeserializeResult { @@ -413,14 +459,21 @@ public class BiomeWrapper implements IBiomeWrapper public final Biome biome; #else public final Holder biome; - #endif + #endif - public BiomeDeserializeResult(boolean success, #if MC_VER < MC_1_18_2 Biome #else Holder #endif biome) + #if MC_VER < MC_1_18_2 + public BiomeDeserializeResult(boolean success, Biome biome) + #else + public BiomeDeserializeResult(boolean success, Holder biome) + #endif { this.success = success; this.biome = biome; } } + //endregion + + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java index f20398970..bcd895020 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java @@ -32,12 +32,20 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +#if MC_VER <= MC_1_12_2 +import net.minecraft.block.*; +import net.minecraft.init.Blocks; +import net.minecraft.block.state.IBlockState; +import net.minecraft.block.properties.IProperty; +import net.minecraftforge.fluids.IFluidBlock; +#else import net.minecraft.tags.BlockTags; import net.minecraft.world.level.block.BeaconBeamBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; +#endif import com.seibel.distanthorizons.core.logging.DhLogger; import java.awt.*; @@ -61,7 +69,7 @@ import net.minecraft.world.level.Level; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.world.level.EmptyBlockGetter; -#else +#elif MC_VER > MC_1_12_2 import net.minecraft.tags.TagKey; import net.minecraft.world.level.Level; import net.minecraft.core.BlockPos; @@ -70,12 +78,15 @@ import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.core.Holder; #endif -#if MC_VER <= MC_1_21_10 +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.ResourceLocation; +#elif MC_VER <= MC_1_21_10 import net.minecraft.resources.ResourceLocation; #else import net.minecraft.resources.Identifier; #endif + public class BlockStateWrapper implements IBlockStateWrapper { /** example "minecraft:water" */ @@ -87,7 +98,11 @@ public class BlockStateWrapper implements IBlockStateWrapper // must be defined before AIR, otherwise a null pointer will be thrown private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + #if MC_VER <= MC_1_12_2 + public static final ConcurrentHashMap WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>(); + #else public static final ConcurrentHashMap WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>(); + #endif public static final ConcurrentHashMap WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>(); public static final String AIR_STRING = "AIR"; @@ -114,7 +129,11 @@ public class BlockStateWrapper implements IBlockStateWrapper // properties // @Nullable + #if MC_VER <= MC_1_12_2 + public final IBlockState blockState; + #else public final BlockState blockState; + #endif /** technically final, but since it requires a method call to generate it can't be marked as such */ private String serialString; private final int hashCode; @@ -139,27 +158,71 @@ public class BlockStateWrapper implements IBlockStateWrapper // constructors // //==============// //region - /** - * Can be faster than {@link BlockStateWrapper#fromBlockState(BlockState, ILevelWrapper)} + * Can be faster than BlockStateWrapper#fromBlockState(BlockState, ILevelWrapper) * in cases where the same block state is expected to be referenced multiple times. */ + #if MC_VER <= MC_1_12_2 + public static BlockStateWrapper fromBlockState(IBlockState blockState, ILevelWrapper levelWrapper, IBlockStateWrapper guess) + #else public static BlockStateWrapper fromBlockState(BlockState blockState, ILevelWrapper levelWrapper, IBlockStateWrapper guess) + #endif { - BlockState guessBlockState = (guess == null || guess.isAir()) ? null : (BlockState) guess.getWrappedMcObject(); - BlockState inputBlockState = (blockState == null || blockState.isAir()) ? null : blockState; - - if (guess instanceof BlockStateWrapper - && guessBlockState == inputBlockState) - { - return (BlockStateWrapper) guess; - } - else + if (guess == null) { return fromBlockState(blockState, levelWrapper); } + + + // guess block state + BlockStateWrapper wrapperGuess = (BlockStateWrapper) guess; + #if MC_VER <= MC_1_12_2 + IBlockState guessBlockState; + #else + BlockState guessBlockState; + #endif + if(isAir(wrapperGuess.blockState)) + { + guessBlockState = null; + } + else + { + #if MC_VER <= MC_1_12_2 + guessBlockState = (IBlockState) guess.getWrappedMcObject(); + #else + guessBlockState = (BlockState) guess.getWrappedMcObject(); + #endif + } + + // input block state + #if MC_VER <= MC_1_12_2 + IBlockState inputBlockState; + #else + BlockState inputBlockState; + #endif + if (isAir(blockState)) + { + inputBlockState = null; + } + else + { + inputBlockState = blockState; + } + + + if (guessBlockState == inputBlockState) + { + return (BlockStateWrapper) guess; + } + + return fromBlockState(blockState, levelWrapper); } + + #if MC_VER <= MC_1_12_2 + public static BlockStateWrapper fromBlockState(@Nullable IBlockState blockState, ILevelWrapper levelWrapper) + #else public static BlockStateWrapper fromBlockState(@Nullable BlockState blockState, ILevelWrapper levelWrapper) + #endif { // air is a special case if (isAir(blockState)) @@ -208,9 +271,12 @@ public class BlockStateWrapper implements IBlockStateWrapper } } } - private BlockStateWrapper( - @Nullable BlockState blockState, ILevelWrapper levelWrapper, - @Nullable DhApiBlockStateWrapperCreatedEvent.EventParam overrideEventParam) + + #if MC_VER <= MC_1_12_2 + private BlockStateWrapper(@Nullable IBlockState blockState, ILevelWrapper levelWrapper, @Nullable DhApiBlockStateWrapperCreatedEvent.EventParam overrideEventParam) + #else + private BlockStateWrapper(@Nullable BlockState blockState, ILevelWrapper levelWrapper, @Nullable DhApiBlockStateWrapperCreatedEvent.EventParam overrideEventParam) + #endif { this.blockState = blockState; this.serialString = serialize(blockState, levelWrapper); @@ -228,11 +294,13 @@ public class BlockStateWrapper implements IBlockStateWrapper } else { - #if MC_VER < MC_1_20_1 - this.isLiquid = this.blockState.getMaterial().isLiquid() || !this.blockState.getFluidState().isEmpty(); - #else + #if MC_VER <= MC_1_12_2 + this.isLiquid = this.blockState.getMaterial().isLiquid() || this.blockState.getBlock() instanceof IFluidBlock; + #elif MC_VER < MC_1_20_1 + this.isLiquid = this.blockState.getMaterial().isLiquid() || !this.blockState.getFluidState().isEmpty(); + #else this.isLiquid = !this.blockState.getFluidState().isEmpty(); - #endif + #endif } } @@ -332,9 +400,21 @@ public class BlockStateWrapper implements IBlockStateWrapper && !this.isBeaconBlock) { Block block = this.blockState.getBlock(); + int colorInt; + #if MC_VER <= MC_1_12_2 + if (block instanceof BlockStainedGlass) + { + colorInt = blockState.getValue(BlockStainedGlass.COLOR).getColorValue(); + beaconTintColor = ColorUtil.toColorObjRGB(colorInt); + } + else if (block instanceof BlockStainedGlassPane) + { + colorInt = blockState.getValue(BlockStainedGlassPane.COLOR).getColorValue(); + beaconTintColor = ColorUtil.toColorObjRGB(colorInt); + } + #else if (block instanceof BeaconBeamBlock) { - int colorInt; #if MC_VER <= MC_1_19_4 colorInt = ((BeaconBeamBlock) block).getColor().getMaterialColor().col; #else @@ -343,6 +423,7 @@ public class BlockStateWrapper implements IBlockStateWrapper beaconTintColor = ColorUtil.toColorObjRGB(colorInt); } + #endif } this.beaconTintColor = beaconTintColor; @@ -392,8 +473,10 @@ public class BlockStateWrapper implements IBlockStateWrapper if (this.blockState != null) { int mcColor = 0; - - #if MC_VER < MC_1_20_1 + + #if MC_VER <= MC_1_12_2 + mcColor = this.blockState.getMaterial().getMaterialMapColor().colorValue; + #elif MC_VER < MC_1_20_1 mcColor = this.blockState.getMaterial().getColor().col; #else mcColor = this.blockState.getMapColor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).col; @@ -420,7 +503,7 @@ public class BlockStateWrapper implements IBlockStateWrapper #if MC_VER < MC_1_20_1 this.isSolid = this.blockState.getMaterial().isSolid(); #else - this.isSolid = !this.blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).isEmpty(); + this.isSolid = !this.blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).isEmpty(); #endif } } @@ -431,76 +514,193 @@ public class BlockStateWrapper implements IBlockStateWrapper // static constructor helpers // //region - private static EDhApiBlockMaterial calculateEDhApiBlockMaterialId( - @Nullable BlockState blockState, - String lowercaseSerialString, - boolean isLiquid - ) + #if MC_VER <= MC_1_12_2 + private static EDhApiBlockMaterial calculateEDhApiBlockMaterialId(@Nullable IBlockState blockState, String lowercaseSerialString, boolean isLiquid) + #else + private static EDhApiBlockMaterial calculateEDhApiBlockMaterialId(@Nullable BlockState blockState, String lowercaseSerialString, boolean isLiquid) + #endif { - if (blockState == null) + if (isAir(blockState)) { return EDhApiBlockMaterial.AIR; } - if (blockState.is(BlockTags.LEAVES) + + //========// + // leaves // + //========// + //region + + boolean isLeafBlock; + #if MC_VER <= MC_1_12_2 + isLeafBlock = blockState.getBlock() instanceof BlockLeaves; + #else + isLeafBlock = blockState.is(BlockTags.LEAVES); + #endif + if (isLeafBlock || lowercaseSerialString.contains("bamboo") || lowercaseSerialString.contains("cactus") || lowercaseSerialString.contains("chorus_flower") || lowercaseSerialString.contains("mushroom") - ) + ) { return EDhApiBlockMaterial.LEAVES; } - else if (blockState.is(Blocks.LAVA)) + + //endregion + + + + //======// + // lava // + //======// + //region + + boolean isLavaBlock; + #if MC_VER <= MC_1_12_2 + isLavaBlock = blockState.getBlock() == Blocks.LAVA || blockState.getBlock() == Blocks.FLOWING_LAVA; + #else + isLavaBlock = blockState.is(Blocks.LAVA); + #endif + if (isLavaBlock) { return EDhApiBlockMaterial.LAVA; } - else if (isLiquid - || blockState.is(Blocks.WATER)) + + //endregion + + + + //=======// + // water // + //=======// + //region + + boolean isWaterBlock; + #if MC_VER <= MC_1_12_2 + isWaterBlock = blockState.getBlock() == Blocks.WATER || blockState.getBlock() == Blocks.FLOWING_WATER; + #else + isWaterBlock = blockState.is(Blocks.WATER); + #endif + if (isLiquid + || isWaterBlock) { return EDhApiBlockMaterial.WATER; } - else if (blockState.getSoundType() == SoundType.WOOD + + //endregion + + + + //======// + // wood // + //======// + //region + + boolean isWoodSoundingBlock; + #if MC_VER <= MC_1_12_2 + isWoodSoundingBlock = blockState.getBlock().getSoundType() == SoundType.WOOD; + #else + isWoodSoundingBlock = blockState.getSoundType() == SoundType.WOOD; + #endif + + boolean isCherryWood; + #if MC_VER <= MC_1_19_2 + isCherryWood = false; + #else + isCherryWood = blockState.getSoundType() == SoundType.CHERRY_WOOD; + #endif + + if (isWoodSoundingBlock || lowercaseSerialString.contains("root") - #if MC_VER >= MC_1_19_4 - || blockState.getSoundType() == SoundType.CHERRY_WOOD - #endif - ) + || isCherryWood + ) { return EDhApiBlockMaterial.WOOD; } - else if (blockState.getSoundType() == SoundType.METAL - #if MC_VER >= MC_1_19_2 - || blockState.getSoundType() == SoundType.COPPER - #endif - #if MC_VER >= MC_1_20_4 - || blockState.getSoundType() == SoundType.COPPER_BULB - || blockState.getSoundType() == SoundType.COPPER_GRATE - #endif - ) + + //endregion + + + + //=======// + // metal // + //=======// + //region + + boolean isMetalSoundingBlock; + #if MC_VER <= MC_1_12_2 + isMetalSoundingBlock = blockState.getBlock().getSoundType() == SoundType.METAL; + #else + isMetalSoundingBlock = blockState.getSoundType() == SoundType.METAL; + #endif + + boolean isCopperSounding; + #if MC_VER <= MC_1_18_2 + isCopperSounding = false; + #elif MC_VER <= MC_1_20_2 + isCopperSounding = blockState.getSoundType() == SoundType.COPPER; + #else + isCopperSounding + = blockState.getSoundType() == SoundType.COPPER + || blockState.getSoundType() == SoundType.COPPER_BULB + || blockState.getSoundType() == SoundType.COPPER_GRATE; + #endif + + if (isMetalSoundingBlock + || isCopperSounding) { return EDhApiBlockMaterial.METAL; } - else if ( - lowercaseSerialString.contains("grass_block") - || lowercaseSerialString.contains("grass_slab") - ) + + //endregion + + + + //=======// + // grass // + //=======// + //region + + if (lowercaseSerialString.contains("grass_block") + || lowercaseSerialString.contains("grass_slab") + ) { return EDhApiBlockMaterial.GRASS; } - else if ( + + //endregion + + + + //======// + // dirt // + //======// + //region + + if ( lowercaseSerialString.contains("dirt") - || lowercaseSerialString.contains("gravel") - || lowercaseSerialString.contains("mud") - || lowercaseSerialString.contains("podzol") - || lowercaseSerialString.contains("mycelium") - ) + || lowercaseSerialString.contains("gravel") + || lowercaseSerialString.contains("mud") + || lowercaseSerialString.contains("podzol") + || lowercaseSerialString.contains("mycelium") + ) { return EDhApiBlockMaterial.DIRT; } + + //endregion + + + + //===========// + // deepslate // + //===========// + //region + #if MC_VER >= MC_1_17_1 - else if (blockState.getSoundType() == SoundType.DEEPSLATE + if (blockState.getSoundType() == SoundType.DEEPSLATE || blockState.getSoundType() == SoundType.DEEPSLATE_BRICKS || blockState.getSoundType() == SoundType.DEEPSLATE_TILES || blockState.getSoundType() == SoundType.POLISHED_DEEPSLATE @@ -509,41 +709,75 @@ public class BlockStateWrapper implements IBlockStateWrapper return EDhApiBlockMaterial.DEEPSLATE; } #endif - else if (lowercaseSerialString.contains("snow")) - { - return EDhApiBlockMaterial.SNOW; - } - else if (lowercaseSerialString.contains("sand")) - { - return EDhApiBlockMaterial.SAND; - } - else if (lowercaseSerialString.contains("terracotta")) - { - return EDhApiBlockMaterial.TERRACOTTA; - } - else if (blockState.is(BlockTags.BASE_STONE_NETHER)) + + //endregion + + + + //============// + // netherrack // + //============// + //region + + boolean isNetherRack; + #if MC_VER <= MC_1_12_2 + isNetherRack = blockState.getBlock() == Blocks.NETHERRACK; + #else + isNetherRack = blockState.is(BlockTags.BASE_STONE_NETHER); + #endif + + if (isNetherRack) { return EDhApiBlockMaterial.NETHER_STONE; } - else if (lowercaseSerialString.contains("stone") + + //endregion + + + + //=============// + // misc/simple // + //=============// + //region + + if (lowercaseSerialString.contains("snow")) + { + return EDhApiBlockMaterial.SNOW; + } + + if (lowercaseSerialString.contains("sand")) + { + return EDhApiBlockMaterial.SAND; + } + + if (lowercaseSerialString.contains("terracotta")) + { + return EDhApiBlockMaterial.TERRACOTTA; + } + + if (lowercaseSerialString.contains("stone") || lowercaseSerialString.contains("ore")) { return EDhApiBlockMaterial.STONE; } - else if (blockState.getLightEmission() > 0) + + if (getLightEmission(blockState) > 0) { return EDhApiBlockMaterial.ILLUMINATED; } - else - { - return EDhApiBlockMaterial.UNKNOWN; - } + + //endregion + + + + return EDhApiBlockMaterial.UNKNOWN; } - private static int calculateOpacity( - @Nullable BlockState blockState, - boolean isAir, boolean isLiquid - ) + #if MC_VER <= MC_1_12_2 + private static int calculateOpacity(@Nullable IBlockState blockState, boolean isAir, boolean isLiquid) + #else + private static int calculateOpacity(@Nullable BlockState blockState, boolean isAir, boolean isLiquid) + #endif { // get block properties (defaults to the values used by air) boolean canOcclude = getCanOcclude(blockState); @@ -582,24 +816,40 @@ public class BlockStateWrapper implements IBlockStateWrapper return opacity; } + + #if MC_VER <= MC_1_12_2 + private static boolean getCanOcclude(@Nullable IBlockState blockState) + #else private static boolean getCanOcclude(@Nullable BlockState blockState) + #endif { // defaults to the value used by air boolean canOcclude = false; if (blockState != null) { + #if MC_VER <= MC_1_12_2 + canOcclude = blockState.getMaterial().isSolid(); + #else canOcclude = blockState.canOcclude(); + #endif } return canOcclude; } + + #if MC_VER <= MC_1_12_2 + private static boolean getPropagatesSkyLightDown(@Nullable IBlockState blockState) + #else private static boolean getPropagatesSkyLightDown(@Nullable BlockState blockState) + #endif { // defaults to the value used by air boolean propagatesSkyLightDown = true; if (blockState != null) { - #if MC_VER < MC_1_21_3 + #if MC_VER <= MC_1_12_2 + propagatesSkyLightDown = blockState.getBlock().getLightOpacity(blockState) == 0; + #elif MC_VER < MC_1_21_3 propagatesSkyLightDown = blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); #else propagatesSkyLightDown = blockState.propagatesSkylightDown(); @@ -659,8 +909,10 @@ public class BlockStateWrapper implements IBlockStateWrapper return waterSurfaceReplacementBlocks; } - ObjectOpenHashSet baseIgnoredBlock = new ObjectOpenHashSet<>(); - waterSurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSurfaceBlockReplacementCsv, baseIgnoredBlock, levelWrapper); + ObjectOpenHashSet baseIgnoredBlockResourceSet = new ObjectOpenHashSet<>(); + waterSurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSurfaceBlockReplacementCsv, baseIgnoredBlockResourceSet, levelWrapper); + waterSubsurfaceReplacementBlocks.remove(AIR); + return waterSurfaceReplacementBlocks; } public static ObjectOpenHashSet getWaterSubsurfaceReplacementBlocks(ILevelWrapper levelWrapper) @@ -671,8 +923,12 @@ public class BlockStateWrapper implements IBlockStateWrapper return waterSubsurfaceReplacementBlocks; } - ObjectOpenHashSet baseIgnoredBlock = new ObjectOpenHashSet<>(); - waterSubsurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSubSurfaceBlockReplacementCsv, baseIgnoredBlock, levelWrapper); + ObjectOpenHashSet baseIgnoredBlockResourceSet = new ObjectOpenHashSet<>(); + waterSubsurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSubSurfaceBlockReplacementCsv, baseIgnoredBlockResourceSet, levelWrapper); + // air will be present if any invalid resource locations are present + // but we don't want to replace air with water, that'll cause monoliths + waterSubsurfaceReplacementBlocks.remove(AIR); + return waterSubsurfaceReplacementBlocks; } public static IBlockStateWrapper getWaterBlockStateWrapper(ILevelWrapper levelWrapper) @@ -740,8 +996,17 @@ public class BlockStateWrapper implements IBlockStateWrapper if (defaultBlockStateToIgnore != AIR) { // add all possible blockstates (to account for light blocks with different light values and such) + #if MC_VER <= MC_1_12_2 + List blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getBlockState().getValidStates(); + #else List blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates(); + #endif + + #if MC_VER <= MC_1_12_2 + for (IBlockState blockState : blockStatesToIgnore) + #else for (BlockState blockState : blockStatesToIgnore) + #endif { BlockStateWrapper newBlockToIgnore = fromBlockState(blockState, levelWrapper); blockStateWrappers.add(newBlockToIgnore); @@ -788,7 +1053,25 @@ public class BlockStateWrapper implements IBlockStateWrapper public int getOpacity() { return this.opacity; } @Override - public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; } + public int getLightEmission() { return getLightEmission(this.blockState); } + #if MC_VER <= MC_1_12_2 + public static int getLightEmission(IBlockState blockState) + #else + public static int getLightEmission(BlockState blockState) + #endif + { + if (blockState == null) + { + return 0; + } + + #if MC_VER <= MC_1_12_2 + return blockState.getLightValue(); + #else + return blockState.getLightEmission(); + #endif + } + @Override public String getSerialString() { return this.serialString; } @@ -798,7 +1081,23 @@ public class BlockStateWrapper implements IBlockStateWrapper @Override public boolean isAir() { return isAir(this.blockState); } - public static boolean isAir(BlockState blockState) { return blockState == null || blockState.isAir(); } + #if MC_VER <= MC_1_12_2 + public static boolean isAir(IBlockState blockState) + #else + public static boolean isAir(BlockState blockState) + #endif + { + if (blockState == null) + { + return true; + } + + #if MC_VER <= MC_1_12_2 + return blockState.getBlock() == Blocks.AIR; + #else + return blockState.isAir(); + #endif + } @Override public boolean isSolid() { return this.isSolid; } @@ -832,7 +1131,11 @@ public class BlockStateWrapper implements IBlockStateWrapper //=======================// //region + #if MC_VER <= MC_1_12_2 + private static String serialize(IBlockState blockState, ILevelWrapper levelWrapper) + #else private static String serialize(BlockState blockState, ILevelWrapper levelWrapper) + #endif { if (blockState == null) { @@ -854,7 +1157,9 @@ public class BlockStateWrapper implements IBlockStateWrapper Identifier resourceLocation; #endif - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + resourceLocation = blockState.getBlock().getRegistryName(); + #elif MC_VER <= MC_1_17_1 resourceLocation = Registry.BLOCK.getKey(blockState.getBlock()); #elif MC_VER <= MC_1_19_2 resourceLocation = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).getKey(blockState.getBlock()); @@ -953,7 +1258,9 @@ public class BlockStateWrapper implements IBlockStateWrapper #endif Block block; - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + block = Block.REGISTRY.getObject(resourceLocation); + #elif MC_VER <= MC_1_17_1 block = Registry.BLOCK.get(resourceLocation); #elif MC_VER <= MC_1_19_2 net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); @@ -982,11 +1289,24 @@ public class BlockStateWrapper implements IBlockStateWrapper // attempt to find the blockstate from all possibilities + #if MC_VER <= MC_1_12_2 + IBlockState foundState = null; + #else BlockState foundState = null; + #endif if (blockStatePropertiesString != null) { + #if MC_VER <= MC_1_12_2 + List possibleStateList = block.getBlockState().getValidStates(); + #else List possibleStateList = block.getStateDefinition().getPossibleStates(); + #endif + + #if MC_VER <= MC_1_12_2 + for (IBlockState possibleState : possibleStateList) + #else for (BlockState possibleState : possibleStateList) + #endif { String possibleStatePropertiesString = serializeBlockStateProperties(possibleState); if (possibleStatePropertiesString.equals(blockStatePropertiesString)) @@ -1010,7 +1330,12 @@ public class BlockStateWrapper implements IBlockStateWrapper } } - foundState = block.defaultBlockState(); + + #if MC_VER <= MC_1_12_2 + foundState = block.getDefaultState(); + #else + foundState = block.defaultBlockState(); + #endif } foundWrapper = fromBlockState(foundState, levelWrapper); @@ -1035,26 +1360,44 @@ public class BlockStateWrapper implements IBlockStateWrapper } /** used to compare and save BlockStates based on their properties */ + #if MC_VER <= MC_1_12_2 + private static String serializeBlockStateProperties(IBlockState blockState) + #else private static String serializeBlockStateProperties(BlockState blockState) + #endif { // get the property list for this block (doesn't contain this block state's values, just the names and possible values) - java.util.Collection> blockPropertyCollection = blockState.getProperties(); + #if MC_VER <= MC_1_12_2 + java.util.Collection> blockPropertyCollection = blockState.getPropertyKeys(); + List> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection); + #else + java.util.Collection> blockPropertyCollection = blockState.getProperties();; + List> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection); + #endif // alphabetically sort the list so they are always in the same order - List> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection); sortedBlockPropteryList.sort((a, b) -> a.getName().compareTo(b.getName())); StringBuilder stringBuilder = new StringBuilder(); + #if MC_VER <= MC_1_12_2 + for (IProperty property : sortedBlockPropteryList) + #else for (net.minecraft.world.level.block.state.properties.Property property : sortedBlockPropteryList) + #endif { String propertyName = property.getName(); String value = "NULL"; + + #if MC_VER <= MC_1_12_2 + value = blockState.getValue(property).toString(); + #else if (blockState.hasProperty(property)) { value = blockState.getValue(property).toString(); } + #endif stringBuilder.append("{"); stringBuilder.append(propertyName).append(RESOURCE_LOCATION_SEPARATOR).append(value); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/ClientBlockStateColorCache.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/ClientBlockStateColorCache.java index ee776f4b8..f83856c39 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/ClientBlockStateColorCache.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/ClientBlockStateColorCache.java @@ -32,22 +32,31 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +#if MC_VER <= MC_1_12_2 +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumBlockRenderType; +import net.minecraft.util.EnumFacing; +import net.minecraft.block.BlockRotatedPillar; +import net.minecraft.block.*; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.renderer.color.BlockColors; +import net.minecraft.util.math.BlockPos; +#else import net.minecraft.core.Direction; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; -import com.seibel.distanthorizons.core.logging.DhLogger; import net.minecraft.world.level.block.state.properties.SlabType; +#endif +import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; +import java.util.*; import java.util.concurrent.locks.ReentrantLock; #if MC_VER >= MC_1_19_2 import net.minecraft.util.RandomSource; #else -import java.util.Random; #endif #if MC_VER < MC_1_21_5 @@ -64,19 +73,32 @@ import net.minecraft.client.color.block.BlockTintSource; /** * This stores and calculates the colors - * the given {@link BlockState} should have based + * the given BlockState should have based * on the given {@link IClientLevelWrapper}. - * + * * @see ColorUtil */ public class ClientBlockStateColorCache { private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + #if MC_VER <= MC_1_12_2 + private static final Minecraft MC = Minecraft.getMinecraft(); + #else private static final Minecraft MC = Minecraft.getInstance(); + #endif + + #if MC_VER <= MC_1_12_2 + #else private static final HashSet BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>(); + #endif + + #if MC_VER <= MC_1_12_2 + private static final HashSet BROKEN_BLOCK_STATES = new HashSet<>(); + #else private static final HashSet BROKEN_BLOCK_STATES = new HashSet<>(); + #endif /** * Methods using MC's "RandomSource" object aren't thread safe
@@ -88,18 +110,33 @@ public class ClientBlockStateColorCache */ private static final ReentrantLock RESOLVE_LOCK = new ReentrantLock(); + public static final int INVALID_COLOR = -1; + /** This is the order each direction on a block is processed when attempting to get the texture/color */ + #if MC_VER <= MC_1_12_2 + private static final @Nullable EnumFacing[] COLOR_RESOLUTION_DIRECTION_ORDER = + { + EnumFacing.UP, + null, // null represents "unculled" faces, IE the top of farmland + EnumFacing.NORTH, + EnumFacing.EAST, + EnumFacing.WEST, + EnumFacing.SOUTH, + EnumFacing.DOWN + }; + #else private static final @Nullable Direction[] COLOR_RESOLUTION_DIRECTION_ORDER = - { + { Direction.UP, null, // null represents "unculled" faces, IE the top of farmland - Direction.NORTH, - Direction.EAST, - Direction.WEST, - Direction.SOUTH, - Direction.DOWN + Direction.NORTH, + Direction.EAST, + Direction.WEST, + Direction.SOUTH, + Direction.DOWN }; + #endif private static final int FLOWER_COLOR_SCALE = 5; @@ -113,7 +150,11 @@ public class ClientBlockStateColorCache #endif private final IClientLevelWrapper clientLevelWrapper; + #if MC_VER <= MC_1_12_2 + private final IBlockState blockState; + #else private final BlockState blockState; + #endif private final BlockStateWrapper blockStateWrapper; private boolean isColorResolved = false; @@ -191,8 +232,10 @@ public class ClientBlockStateColorCache }; // these are threadlocals since AbstractDhTintGetter use local variables to handle color queries + #if MC_VER > MC_1_12_2 private static final ThreadLocal TintWithoutLevelOverrideGetter = ThreadLocal.withInitial(TintWithoutLevelOverrider::new); private static final ThreadLocal TintOverrideGetter = ThreadLocal.withInitial(TintGetterOverride::new); + #endif private static final ThreadLocal ColorOverrideEventParamGetter = ThreadLocal.withInitial(DhApiBlockColorOverrideEvent.EventParam::new); //endregion @@ -204,7 +247,11 @@ public class ClientBlockStateColorCache //=============// //region + #if MC_VER <= MC_1_12_2 + public ClientBlockStateColorCache(IBlockState blockState, IClientLevelWrapper clientLevelWrapper) + #else public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper clientLevelWrapper) + #endif { this.blockState = blockState; this.blockStateWrapper = BlockStateWrapper.fromBlockState(blockState, clientLevelWrapper); @@ -220,6 +267,7 @@ public class ClientBlockStateColorCache //===================// // color calculation // //===================// + //region private void resolveColors() { @@ -233,17 +281,44 @@ public class ClientBlockStateColorCache // getQuads() isn't thread safe so we need to put this logic in a lock RESOLVE_LOCK.lock(); - if (this.blockState.getFluidState().isEmpty()) + #if MC_VER <= MC_1_12_2 + if (this.blockState.getRenderType() == EnumBlockRenderType.ENTITYBLOCK_ANIMATED) + { + this.needPostTinting = false; + this.tintIndex = 0; + this.baseColor = ColorUtil.argbToInt(255, + this.blockStateWrapper.getMapColor().getRed(), + this.blockStateWrapper.getMapColor().getGreen(), + this.blockStateWrapper.getMapColor().getBlue()); + this.isColorResolved = true; + return; + } + #endif + + if (!this.blockStateWrapper.isLiquid()) { // look for the first non-empty direction List quads = null; - for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER) + + #if MC_VER <= MC_1_12_2 + EnumFacing direction; + #else + Direction direction; + #endif + + for (int i = 0; i < COLOR_RESOLUTION_DIRECTION_ORDER.length; i++) { + direction = COLOR_RESOLUTION_DIRECTION_ORDER[i]; quads = this.getQuadsForDirection(direction); if (quads != null && !quads.isEmpty() && !( + #if MC_VER <= MC_1_12_2 + this.blockState.getBlock() instanceof BlockRotatedPillar + && direction == EnumFacing.UP + #else this.blockState.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP + #endif ) ) { @@ -260,39 +335,57 @@ public class ClientBlockStateColorCache && !quads.isEmpty() && quads.get(0) != null) { - BakedQuad firstQuad = quads.get(0); + try + { + BakedQuad firstQuad = quads.get(0); + + #if MC_VER <= MC_1_12_2 + this.needPostTinting = firstQuad.hasTintIndex(); + #elif MC_VER <= MC_1_21_11 + this.needPostTinting = firstQuad.isTinted(); + #else + this.needPostTinting = firstQuad.materialInfo().isTinted(); + #endif - #if MC_VER <= MC_1_21_11 - this.needPostTinting = firstQuad.isTinted(); - #else - this.needPostTinting = firstQuad.materialInfo().isTinted(); - #endif - - #if MC_VER <= MC_1_21_4 - this.tintIndex = firstQuad.getTintIndex(); - #elif MC_VER <= MC_1_21_11 - this.tintIndex = firstQuad.tintIndex(); - #else - this.tintIndex = firstQuad.materialInfo().tintIndex(); - #endif - - #if MC_VER < MC_1_17_1 - this.baseColor = calculateColorFromTexture( - firstQuad.sprite, - EColorMode.getColorMode(this.blockState.getBlock())); - #elif MC_VER < MC_1_21_5 - this.baseColor = calculateColorFromTexture( - firstQuad.getSprite(), - EColorMode.getColorMode(this.blockState.getBlock())); - #elif MC_VER <= MC_1_21_11 - this.baseColor = calculateColorFromTexture( - firstQuad.sprite(), - EColorMode.getColorMode(this.blockState.getBlock())); - #else - this.baseColor = calculateColorFromTexture( - firstQuad.materialInfo().sprite(), - EColorMode.getColorMode(this.blockState.getBlock())); - #endif + #if MC_VER <= MC_1_21_4 + this.tintIndex = firstQuad.getTintIndex(); + #elif MC_VER <= MC_1_21_11 + this.tintIndex = firstQuad.tintIndex(); + #else + this.tintIndex = firstQuad.materialInfo().tintIndex(); + #endif + + #if MC_VER < MC_1_17_1 && MC_VER > MC_1_12_2 + this.baseColor = calculateColorFromTexture( + firstQuad.sprite, + EColorMode.getColorMode(this.blockState.getBlock())); + #elif MC_VER < MC_1_21_5 + this.baseColor = calculateColorFromTexture( + firstQuad.getSprite(), + EColorMode.getColorMode(this.blockState.getBlock())); + #elif MC_VER <= MC_1_21_11 + this.baseColor = calculateColorFromTexture( + firstQuad.sprite(), + EColorMode.getColorMode(this.blockState.getBlock())); + #else + this.baseColor = calculateColorFromTexture( + firstQuad.materialInfo().sprite(), + EColorMode.getColorMode(this.blockState.getBlock())); + #endif + } + catch (Exception e) + { + // Shouldn't normally happen, but there was at least + // one report of MC's texture being un-loaded + // which prevented us from getting the texture. + // So we should have some basic backup logic. + + LOGGER.warn("Failed to get texture color for block ["+this.blockStateWrapper.getSerialString()+"] due to: ["+e.getMessage()+"], falling back to particle color."); + + this.needPostTinting = false; + this.tintIndex = 0; + this.baseColor = this.getParticleIconColor(); + } } else { @@ -322,20 +415,43 @@ public class ClientBlockStateColorCache @Nullable private List getUnculledQuads() { return this.getQuadsForDirection(null); } @Nullable + #if MC_VER <= MC_1_12_2 + private List getQuadsForDirection(@Nullable EnumFacing direction) + #else private List getQuadsForDirection(@Nullable Direction direction) + #endif { + #if MC_VER <= MC_1_12_2 + IBlockState effectiveBlockState = this.blockState; + #else BlockState effectiveBlockState = this.blockState; + #endif // if this block is a slab, use it's double variant so we can get the top face, // otherwise the color will use the side, which isn't as accurate + #if MC_VER <= MC_1_12_2 + if (this.blockState.getBlock() instanceof BlockSlab && !((BlockSlab) this.blockState.getBlock()).isDouble()) + { + effectiveBlockState = this.blockState.withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP); + } + #else if (this.blockState.getBlock() instanceof SlabBlock) { effectiveBlockState = this.blockState.setValue( SlabBlock.TYPE, SlabType.DOUBLE ); } + #endif List quads; - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + try { + quads = MC.getBlockRendererDispatcher().getModelForState(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM.nextLong()); + } + catch (Exception e) + { + quads = Collections.emptyList(); + } + #elif MC_VER < MC_1_21_5 quads = MC.getModelManager().getBlockModelShaper(). getBlockModel(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM); #elif MC_VER <= MC_1_21_11 @@ -392,29 +508,29 @@ public class ClientBlockStateColorCache //_ OpenGL RGBA format Java Order: 0xAA BB GG RR tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v); + #if MC_VER <= MC_1_12_2 + int b = (tempColor & 0x000000FF); + int g = (tempColor & 0x0000FF00) >>> 8; + int r = (tempColor & 0x00FF0000) >>> 16; + int a = (tempColor & 0xFF000000) >>> 24; + #else int r = (tempColor & 0x000000FF); int g = (tempColor & 0x0000FF00) >>> 8; int b = (tempColor & 0x00FF0000) >>> 16; int a = (tempColor & 0xFF000000) >>> 24; + #endif + int scale = 1; if (colorMode == EColorMode.Leaves) { - //switch (//FIXME add config option) - // case BLACK: - // a = 255; //simulate black background of fast leaves - // break; - // case IGNORE: - if (a == 0) { - continue; //same long grass - } - else - { - a = 255; //just in case there are semi transparent pixels - } - // break; - // case TRANSPARENT: - // break; //do nothing, let it count towards transparency - + if (a == 0) + { + continue; //same long grass + } + else + { + a = 255; //just in case there are semi transparent pixels + } } else if (a == 0 && colorMode != EColorMode.Glass) { @@ -460,7 +576,9 @@ public class ClientBlockStateColorCache } private static int getTextureWidth(TextureAtlasSprite texture) { - #if MC_VER < MC_1_19_4 + #if MC_VER <= MC_1_12_2 + return texture.getIconWidth(); + #elif MC_VER < MC_1_19_4 return texture.getWidth(); #else return texture.contents().width(); @@ -468,7 +586,9 @@ public class ClientBlockStateColorCache } private static int getTextureHeight(TextureAtlasSprite texture) { - #if MC_VER < MC_1_19_4 + #if MC_VER <= MC_1_12_2 + return texture.getIconHeight(); + #elif MC_VER < MC_1_19_4 return texture.getHeight(); #else return texture.contents().height(); @@ -502,7 +622,9 @@ public class ClientBlockStateColorCache private int getParticleIconColor() { return calculateColorFromTexture( - #if MC_VER <= MC_1_21_11 + #if MC_VER <= MC_1_12_2 + Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getTexture(this.blockState), + #elif MC_VER <= MC_1_21_11 Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState), #else Minecraft.getInstance().getModelManager().getBlockStateModelSet().get(this.blockState).particleMaterial().sprite(), @@ -510,16 +632,20 @@ public class ClientBlockStateColorCache EColorMode.getColorMode(this.blockState.getBlock())); } + //endregion + //===============// // public getter // //===============// + //region public int getColor(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource, DhBlockPos blockPos) { // only get the tint if the block needs to be tinted - int tintColor = AbstractDhTintGetter.INVALID_COLOR; + int tintColor = ClientBlockStateColorCache.INVALID_COLOR; + if (this.needPostTinting) { // don't try tinting blocks that don't support our method of tint getting @@ -532,28 +658,62 @@ public class ClientBlockStateColorCache // attempt to get the tint try { + #if MC_VER <= MC_1_12_2 + // 1.12.2 doesn't have BlockAndTintGetter -> get tintColor from biome + WorldClient world = (WorldClient) this.clientLevelWrapper.getWrappedMcObject(); + BlockPos mcPos = new BlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + + Block block = this.blockState.getBlock(); + if (block instanceof BlockGrass + || block instanceof BlockBush) + { + tintColor = biomeWrapper.biome.getGrassColorAtPos(mcPos); + } + else if (block instanceof BlockLeaves) + { + tintColor = biomeWrapper.biome.getFoliageColorAtPos(mcPos); + } + else if (block instanceof BlockLiquid) // We don't want lava to fall into the else block + { + if(block == Blocks.WATER + || block == Blocks.FLOWING_WATER) + { + tintColor = biomeWrapper.biome.getWaterColor(); + } + } + else + { + BlockColors blockColors = Minecraft.getMinecraft().getBlockColors(); + tintColor = blockColors.colorMultiplier(blockState, world, mcPos, this.tintIndex); + + if (tintColor == ClientBlockStateColorCache.INVALID_COLOR) + { + tintColor = blockColors.getColor(blockState, world, mcPos); + } + } + #else // try to use the fast tint getter logic first if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) { try - { + { TintWithoutLevelOverrider tintOverride = TintWithoutLevelOverrideGetter.get(); tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper); // try using DH's cached tint values first if possible tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos)); - if (tintColor == AbstractDhTintGetter.INVALID_COLOR) + if (tintColor == ClientBlockStateColorCache.INVALID_COLOR) { // one or more tint values weren't calculated, // we need MC's color resolver - #if MC_VER <= MC_1_21_11 - tintColor = Minecraft.getInstance() + #if MC_VER <= MC_1_21_11 + tintColor = Minecraft.getInstance() .getBlockColors() .getColor(this.blockState, tintOverride, // tintOverride will save the result of this query to speed up future queries McObjectConverter.Convert(blockPos), this.tintIndex); - #else + #else BlockTintSource tintSource = Minecraft.getInstance() .getBlockColors() .getTintSource(this.blockState, this.tintIndex); @@ -564,18 +724,12 @@ public class ClientBlockStateColorCache { BlockPos mcPos = McObjectConverter.Convert(blockPos); tintColor = tintSource.colorInWorld(this.blockState, tintOverride, mcPos); - if (tintColor == -1) + if (tintColor == ClientBlockStateColorCache.INVALID_COLOR) { tintColor = tintSource.colorAsTerrainParticle(this.blockState, tintOverride, mcPos); } } - if (tintColor == -1) - { - // no color found, use the base color - tintColor = AbstractDhTintGetter.INVALID_COLOR; - } - // save this color to speed up future queries TintWithoutLevelOverrider.setStaticColor(this.blockStateWrapper, biomeWrapper, tintColor); // try to get the blended color with this new information @@ -585,44 +739,47 @@ public class ClientBlockStateColorCache } catch (Exception e) { - #if MC_VER <= MC_1_21_11 - // this exception generally occurs if the tint requires other blocks besides itself - LOGGER.debug("Unable to use ["+ TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e); - BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState); - #else + #if MC_VER <= MC_1_21_11 + // this exception generally occurs if the tint requires other blocks besides itself + LOGGER.debug("Unable to use ["+ TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e); + BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState); + #else // only display the error once per block/biome type to reduce log spam if (!BROKEN_BLOCK_STATES.contains(this.blockState)) { LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e); BROKEN_BLOCK_STATES.add(this.blockState); } - #endif + #endif } } + #endif + // level-specific logic is only needed for MC 1.21.11 and older - #if MC_VER <= MC_1_21_11 - // use the level logic only if requested - if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) - { - // the level shouldn't be used all the time due to it breaking some blocks tinting - // specifically oceans don't render correctly - - TintGetterOverride tintOverride = TintOverrideGetter.get(); - tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper); - - tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos)); - if (tintColor == AbstractDhTintGetter.INVALID_COLOR) + #if MC_VER <= MC_1_21_11 && MC_VER > MC_1_12_2 + // use the level logic only if requested + if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) { - tintColor = Minecraft.getInstance() - .getBlockColors() - .getColor(this.blockState, - tintOverride, - McObjectConverter.Convert(blockPos), - this.tintIndex); + // the level shouldn't be used all the time due to it breaking some blocks tinting + // specifically oceans don't render correctly + + TintGetterOverride tintOverride = TintOverrideGetter.get(); + tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper); + + tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos)); + if (tintColor == ClientBlockStateColorCache.INVALID_COLOR) + { + tintColor = Minecraft.getInstance() + .getBlockColors() + .getColor(this.blockState, + tintOverride, + McObjectConverter.Convert(blockPos), + this.tintIndex); + } } - } - #endif + #endif + } catch (Exception e) { @@ -637,7 +794,7 @@ public class ClientBlockStateColorCache int returnColor; - if (tintColor != AbstractDhTintGetter.INVALID_COLOR) + if (tintColor != ClientBlockStateColorCache.INVALID_COLOR) { returnColor = ColorUtil.multiplyARGBwithRGB(this.baseColor, tintColor); } @@ -667,6 +824,8 @@ public class ClientBlockStateColorCache return returnColor; } + //endregion + //================// @@ -684,14 +843,54 @@ public class ClientBlockStateColorCache static EColorMode getColorMode(Block block) { - if (block instanceof LeavesBlock) + + + + //========// + // leaves // + //========// + //region + + boolean isLeavesBlock; + #if MC_VER <= MC_1_12_2 + isLeavesBlock = block instanceof BlockLeaves; + #else + isLeavesBlock = block instanceof LeavesBlock; + #endif + if (isLeavesBlock) { return Leaves; } - if (block instanceof FlowerBlock) + + //endregion + + + + //========// + // flower // + //========// + //region + + boolean isFlowerBlock; + #if MC_VER <= MC_1_12_2 + isFlowerBlock = block instanceof BlockFlower; + #else + isFlowerBlock = block instanceof FlowerBlock; + #endif + if (isFlowerBlock) { return Flower; } + + //endregion + + + + //=============// + // misc/simple // + //=============// + //region + if (block.toString().contains("glass")) { return Glass; @@ -700,6 +899,11 @@ public class ClientBlockStateColorCache { return Chisel; } + + //endregion + + + return Default; } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TextureAtlasSpriteWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TextureAtlasSpriteWrapper.java index f6a678afd..1fa5f0ae2 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TextureAtlasSpriteWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TextureAtlasSpriteWrapper.java @@ -38,7 +38,10 @@ public class TextureAtlasSpriteWrapper { public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) { - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + int[][] frameData = sprite.getFrameTextureData(frameIndex); + return frameData[0][y * sprite.getIconWidth() + x]; + #elif MC_VER < MC_1_17_1 return sprite.mainImage[0].getPixelRGBA( x + sprite.framesX[frameIndex] * sprite.getWidth(), y + sprite.framesY[frameIndex] * sprite.getHeight()); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintGetterOverride.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintGetterOverride.java index 1e9bfb0e4..3554b5efb 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintGetterOverride.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintGetterOverride.java @@ -18,7 +18,7 @@ */ package com.seibel.distanthorizons.common.wrappers.block; - +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import net.minecraft.core.BlockPos; @@ -189,3 +189,4 @@ public class TintGetterOverride extends AbstractDhTintGetter } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintWithoutLevelOverrider.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintWithoutLevelOverrider.java index 406b625c7..af932f3c8 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintWithoutLevelOverrider.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/TintWithoutLevelOverrider.java @@ -18,7 +18,7 @@ */ package com.seibel.distanthorizons.common.wrappers.block; - +#if MC_VER > MC_1_12_2 import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.LevelReader; @@ -109,3 +109,4 @@ public class TintWithoutLevelOverrider extends AbstractDhTintGetter } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java index 022c3fb93..d6fc4fe41 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java @@ -31,12 +31,19 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; - import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +#else import net.minecraft.core.BlockPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.levelgen.Heightmap; +#endif import com.seibel.distanthorizons.core.logging.DhLogger; @@ -67,9 +74,10 @@ import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.LevelChunkSection; #endif -#if MC_VER <= MC_1_20_4 +#if MC_VER <= MC_1_12_2 +#elif MC_VER <= MC_1_20_4 import net.minecraft.world.level.chunk.ChunkStatus; -#else +#elif MC_VER > MC_1_12_2 import net.minecraft.world.level.chunk.status.ChunkStatus; #endif @@ -86,8 +94,12 @@ public class ChunkWrapper implements IChunkWrapper private static boolean heightmapThreadWarningLogged = false; - + #if MC_VER <= MC_1_12_2 + private final Chunk chunk; + #else private final ChunkAccess chunk; + #endif + private final DhChunkPos chunkPos; private final ILevelWrapper wrappedLevel; @@ -112,13 +124,17 @@ public class ChunkWrapper implements IChunkWrapper //=============// // constructor // //=============// - + //region /** * Note: this constructor should be very * fast since it will be called frequently on the MC * server thread and a slow method will cause server lag. */ + #if MC_VER <= MC_1_12_2 + public ChunkWrapper(Chunk chunk, ILevelWrapper wrappedLevel) + #else public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel) + #endif { this.chunk = chunk; this.wrappedLevel = wrappedLevel; @@ -133,15 +149,22 @@ public class ChunkWrapper implements IChunkWrapper @Override public ChunkWrapper copy() { return new ChunkWrapper(this.chunk, this.wrappedLevel); } + //endregion + //=========// // getters // //=========// + //region @Override public int getHeight() { return getHeight(this.chunk); } + #if MC_VER <= MC_1_12_2 + public static int getHeight(Chunk chunk) + #else public static int getHeight(ChunkAccess chunk) + #endif { #if MC_VER < MC_1_17_1 return 255; @@ -152,7 +175,11 @@ public class ChunkWrapper implements IChunkWrapper @Override public int getInclusiveMinBuildHeight() { return getInclusiveMinBuildHeight(this.chunk); } + #if MC_VER <= MC_1_12_2 + public static int getInclusiveMinBuildHeight(Chunk chunk) + #else public static int getInclusiveMinBuildHeight(ChunkAccess chunk) + #endif { #if MC_VER < MC_1_17_1 return 0; @@ -165,9 +192,15 @@ public class ChunkWrapper implements IChunkWrapper @Override public int getExclusiveMaxBuildHeight() { return getExclusiveMaxBuildHeight(this.chunk); } + #if MC_VER <= MC_1_12_2 + public static int getExclusiveMaxBuildHeight(Chunk chunk) + #else public static int getExclusiveMaxBuildHeight(ChunkAccess chunk) + #endif { - #if MC_VER < MC_1_21_3 + #if MC_VER <= MC_1_12_2 + return 256; + #elif MC_VER < MC_1_21_3 return chunk.getMaxBuildHeight(); #else // +1 since Minecraft made the max value inclusive @@ -188,7 +221,11 @@ public class ChunkWrapper implements IChunkWrapper this.minNonEmptyHeight = this.getInclusiveMinBuildHeight(); // determine the lowest empty section (bottom up) + #if MC_VER <= MC_1_12_2 + ExtendedBlockStorage[] sections = this.chunk.getBlockStorageArray(); + #else LevelChunkSection[] sections = this.chunk.getSections(); + #endif for (int index = 0; index < sections.length; index++) { if (sections[index] == null) @@ -220,7 +257,11 @@ public class ChunkWrapper implements IChunkWrapper this.maxNonEmptyHeight = this.getExclusiveMaxBuildHeight(); // determine the highest empty section (top down) + #if MC_VER <= MC_1_12_2 + ExtendedBlockStorage[] sections = this.chunk.getBlockStorageArray(); + #else LevelChunkSection[] sections = this.chunk.getSections(); + #endif for (int index = sections.length-1; index >= 0; index--) { // update at each position to fix using the max height if the chunk is empty @@ -240,11 +281,13 @@ public class ChunkWrapper implements IChunkWrapper return this.maxNonEmptyHeight; } + #if MC_VER <= MC_1_12_2 + private static boolean isChunkSectionEmpty(ExtendedBlockStorage section) + #else private static boolean isChunkSectionEmpty(LevelChunkSection section) + #endif { - #if MC_VER == MC_1_16_5 - return section.isEmpty(); - #elif MC_VER == MC_1_17_1 + #if MC_VER <= MC_1_17_1 return section.isEmpty(); #else return section.hasOnlyAir(); @@ -322,7 +365,11 @@ public class ChunkWrapper implements IChunkWrapper // will be null if we want to use MC heightmaps if (this.solidHeightMap == null) { + #if MC_VER <= MC_1_12_2 + return this.chunk.getHeightValue(xRel, zRel); + #else return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel); + #endif } else { @@ -337,19 +384,30 @@ public class ChunkWrapper implements IChunkWrapper if (this.lightBlockingHeightMap == null) { + #if MC_VER <= MC_1_12_2 + return this.chunk.getHeightValue(xRel, zRel); + #else return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel); + #endif } else { return this.lightBlockingHeightMap[xRel][zRel]; - } + } } @Override public IBiomeWrapper getBiome(int relX, int relY, int relZ) { - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get(); + blockPos.setPos(relX, relY, relZ); + + World world = (World) this.wrappedLevel.getWrappedMcObject(); + + return BiomeWrapper.getBiomeWrapper(this.chunk.getBiome(blockPos, world.getBiomeProvider()), wrappedLevel); + #elif MC_VER < MC_1_17_1 return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome( relX >> 2, relY >> 2, relZ >> 2), this.wrappedLevel); @@ -357,10 +415,6 @@ public class ChunkWrapper implements IChunkWrapper return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome( QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)), this.wrappedLevel); - #elif MC_VER < MC_1_18_2 - return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome( - QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)), - this.wrappedLevel); #else //Now returns a Holder instead of Biome return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome( @@ -376,9 +430,13 @@ public class ChunkWrapper implements IChunkWrapper BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get(); + #if MC_VER <= MC_1_12_2 + blockPos.setPos(relX, relY, relZ); + #else blockPos.setX(relX); blockPos.setY(relY); blockPos.setZ(relZ); + #endif try { @@ -401,9 +459,13 @@ public class ChunkWrapper implements IChunkWrapper this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ); BlockPos.MutableBlockPos pos = (BlockPos.MutableBlockPos)mcBlockPos.getWrappedMcObject(); + #if MC_VER <= MC_1_12_2 + pos.setPos(relX, relY, relZ); + #else pos.setX(relX); pos.setY(relY); pos.setZ(relZ); + #endif try { @@ -513,8 +575,14 @@ public class ChunkWrapper implements IChunkWrapper @Override public DhChunkPos getChunkPos() { return this.chunkPos; } - public ChunkAccess getChunk() { return this.chunk; } + #if MC_VER <= MC_1_12_2 + public Chunk getChunk() + #else + public ChunkAccess getChunk() + #endif + { return this.chunk; } + #if MC_VER > MC_1_12_2 public void trySetStatus(ChunkStatus status) { trySetStatus(this.getChunk(), status); } /** does nothing if the chunk object doesn't support setting it's status */ public static void trySetStatus(ChunkAccess chunk, ChunkStatus status) @@ -538,21 +606,53 @@ public class ChunkWrapper implements IChunkWrapper return chunk.getPersistedStatus(); #endif } + #endif @Override - public int getMaxBlockX() { return this.chunk.getPos().getMaxBlockX(); } + public int getMaxBlockX() + { + #if MC_VER <= MC_1_12_2 + return this.chunk.getPos().getXEnd(); + #else + return this.chunk.getPos().getMaxBlockX(); + #endif + } @Override - public int getMaxBlockZ() { return this.chunk.getPos().getMaxBlockZ(); } + public int getMaxBlockZ() + { + #if MC_VER <= MC_1_12_2 + return this.chunk.getPos().getZEnd(); + #else + return this.chunk.getPos().getMaxBlockZ(); + #endif + } @Override - public int getMinBlockX() { return this.chunk.getPos().getMinBlockX(); } + public int getMinBlockX() + { + #if MC_VER <= MC_1_12_2 + return this.chunk.getPos().getXStart(); + #else + return this.chunk.getPos().getMinBlockX(); + #endif + } @Override - public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); } + public int getMinBlockZ() + { + #if MC_VER <= MC_1_12_2 + return this.chunk.getPos().getZStart(); + #else + return this.chunk.getPos().getMinBlockZ(); + #endif + } + + //endregion //==========// // lighting // //==========// + //region @Override public void setIsDhSkyLightCorrect(boolean isDhLightCorrect) { this.isDhSkyLightCorrect = isDhLightCorrect; } @@ -629,8 +729,23 @@ public class ChunkWrapper implements IChunkWrapper { this.blockLightPosList = new ArrayList<>(); - - #if MC_VER < MC_1_20_1 + //1.12.2 doesn't store lights we must bruteforce it + #if MC_VER <= MC_1_12_2 + for (int x = 0; x < 16; x++) + { + for (int z = 0; z < 16; z++) + { + for (int y = 0; y < 256; y++) + { + IBlockState blockState = this.chunk.getBlockState(x, y, z); + if (blockState.getLightValue() > 0) + { + this.blockLightPosList.add(new DhBlockPos(this.chunk.getPos().getXStart() + x, y, this.chunk.getPos().getZStart() + z)); + } + } + } + } + #elif MC_VER < MC_1_20_1 this.chunk.getLights().forEach((blockPos) -> { this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ())); @@ -652,11 +767,14 @@ public class ChunkWrapper implements IChunkWrapper return this.blockLightPosList; } + //endregion + //================// // base overrides // //================// + //region @Override public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); } @@ -672,4 +790,8 @@ public class ChunkWrapper implements IChunkWrapper // return this.blockBiomeHashCode; //} + //endregion + + + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/DhScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/DhScreen.java index b2f4f3571..87da07d77 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/DhScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/DhScreen.java @@ -1,12 +1,19 @@ package com.seibel.distanthorizons.common.wrappers.gui; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.text.ITextComponent; +#else import net.minecraft.client.gui.Font; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +#endif -#if MC_VER < MC_1_20_1 +#if MC_VER <= MC_1_12_2 +#elif MC_VER < MC_1_20_1 import com.mojang.blaze3d.vertex.PoseStack; #elif MC_VER <= MC_1_21_11 import net.minecraft.client.gui.GuiGraphics; @@ -16,26 +23,73 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import java.util.List; +#if MC_VER <= MC_1_12_2 +public class DhScreen extends GuiScreen +#else public class DhScreen extends Screen +#endif { + #if MC_VER <= MC_1_12_2 + protected ITextComponent title; + #endif - protected DhScreen(Component $$0) + #if MC_VER <= MC_1_12_2 + protected DhScreen(ITextComponent title) { - super($$0); + this.title = title; } + #else + protected DhScreen(Component title) + { + super(title); + } + #endif // addRenderableWidget in 1.17 and over // addButton in 1.16 and below + #if MC_VER <= MC_1_12_2 + protected GuiButton addBtn(GuiButton button) + #else protected Button addBtn(Button button) + #endif { - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + this.buttonList.add(button); + return button; + #elif MC_VER < MC_1_17_1 return this.addButton(button); #else return this.addRenderableWidget(button); #endif } - #if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + @Override + protected void actionPerformed(GuiButton button) + { + OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(button); + if (handler != null) + { + handler.pressed(button); + } + } + + protected void DhDrawCenteredString(ITextComponent text, int x, int y, int color) { + drawCenteredString(fontRenderer, text.getFormattedText(), x, y, color); + } + + protected void DhDrawString(ITextComponent text, int x, int y, int color) { + drawString(fontRenderer, text.getFormattedText(), x, y, color); + } + + protected void DhRenderComponentTooltip(List list, int x, int y) { + drawHoveringText(list.stream().map(ITextComponent::getFormattedText).toList(), x, y, fontRenderer); + } + + protected void DhRenderTooltip(ITextComponent text, int x, int y) { + drawHoveringText(List.of(text.getFormattedText()), x, y, fontRenderer); + } + #elif MC_VER < MC_1_20_1 protected void DhDrawCenteredString(PoseStack guiStack, Font font, Component text, int x, int y, int color) { drawCenteredString(guiStack, font, text, x, y, color); @@ -112,7 +166,4 @@ public class DhScreen extends Screen guiStack.setTooltipForNextFrame(font, text, x, y); } #endif - - - } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GetConfigScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GetConfigScreen.java index 9fc094553..6b86db0b1 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GetConfigScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GetConfigScreen.java @@ -4,14 +4,22 @@ import com.seibel.distanthorizons.common.wrappers.gui.classicConfig.ClassicConfi import com.seibel.distanthorizons.core.config.ConfigHandler; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.coreapi.ModInfo; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.GuiScreen; +#else import net.minecraft.client.gui.screens.Screen; +#endif import com.seibel.distanthorizons.core.logging.DhLogger; public class GetConfigScreen { protected static final DhLogger LOGGER = new DhLoggerBuilder().build(); + #if MC_VER <= MC_1_12_2 + public static GuiScreen getScreen(GuiScreen parent) + #else public static Screen getScreen(Screen parent) + #endif { if (ModInfo.IS_DEV_BUILD) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GuiHelper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GuiHelper.java index 46fe7010d..8df4ce1ac 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GuiHelper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/GuiHelper.java @@ -1,11 +1,21 @@ package com.seibel.distanthorizons.common.wrappers.gui; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; +import java.util.HashMap; +import java.util.Map; +#else import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +#endif -#if MC_VER < MC_1_19_2 +#if MC_VER < MC_1_19_2 && MC_VER > MC_1_12_2 import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; #endif @@ -15,57 +25,99 @@ public class GuiHelper /** * Helper static methods for versional compat */ + #if MC_VER <= MC_1_12_2 + public static final Map HANDLER_BY_BUTTON = new HashMap<>(); + #endif + + #if MC_VER <= MC_1_12_2 + public static GuiButton MakeBtn(ITextComponent base, int posX, int posZ, int width, int height, OnPressed action) + #else public static Button MakeBtn(Component base, int posX, int posZ, int width, int height, Button.OnPress action) + #endif { - #if MC_VER < MC_1_19_4 + #if MC_VER <= MC_1_12_2 + GuiButton button = new GuiButton(HANDLER_BY_BUTTON.size(), posX, posZ, width, height, base.getFormattedText()); + HANDLER_BY_BUTTON.put(button, action); + return button; + #elif MC_VER < MC_1_19_4 return new Button(posX, posZ, width, height, base, action); #else return Button.builder(base, action).bounds(posX, posZ, width, height).build(); #endif } + #if MC_VER <= MC_1_12_2 + public static ITextComponent TextOrLiteral(String text) + #else public static MutableComponent TextOrLiteral(String text) + #endif { - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + return new TextComponentString(text); + #elif MC_VER < MC_1_19_2 return new TextComponent(text); #else return Component.literal(text); #endif } + #if MC_VER <= MC_1_12_2 + public static ITextComponent TextOrTranslatable(String text) + #else public static MutableComponent TextOrTranslatable(String text) + #endif { - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + return new TextComponentString(text); + #elif MC_VER < MC_1_19_2 return new TextComponent(text); #else return Component.translatable(text); #endif } + #if MC_VER <= MC_1_12_2 + public static ITextComponent Translatable(String text, Object... args) + #else public static MutableComponent Translatable(String text, Object... args) + #endif { - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + return new TextComponentTranslation(text, args); + #elif MC_VER < MC_1_19_2 return new TranslatableComponent(text, args); #else return Component.translatable(text, args); #endif } - public static void SetX(AbstractWidget w, int x) + #if MC_VER <= MC_1_12_2 + public static void SetX(GuiButton widget, int x) + #else + public static void SetX(AbstractWidget widget, int x) + #endif { #if MC_VER < MC_1_19_4 - w.x = x; + widget.x = x; #else - w.setX(x); + widget.setX(x); #endif } - public static void SetY(AbstractWidget w, int y) + #if MC_VER <= MC_1_12_2 + public static void SetY(GuiTextField textField, int y) { textField.y = y; } + #endif + + #if MC_VER <= MC_1_12_2 + public static void SetY(GuiButton widget, int y) + #else + public static void SetY(AbstractWidget widget, int y) + #endif { #if MC_VER < MC_1_19_4 - w.y = y; + widget.y = y; #else - w.setY(y); + widget.setY(y); #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/LangWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/LangWrapper.java index 7f14108fd..17136c8f3 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/LangWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/LangWrapper.java @@ -1,21 +1,34 @@ package com.seibel.distanthorizons.common.wrappers.gui; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.resources.I18n; +#else import net.minecraft.client.resources.language.I18n; +#endif public class LangWrapper implements ILangWrapper { public static final LangWrapper INSTANCE = new LangWrapper(); + @Override public boolean langExists(String str) { + #if MC_VER <= MC_1_12_2 + return I18n.hasKey(str); + #else return I18n.exists(str); + #endif } @Override public String getLang(String str) { + #if MC_VER <= MC_1_12_2 + return I18n.format(str); + #else return I18n.get(str); + #endif } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/MinecraftScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/MinecraftScreen.java index 9e1f4ae30..2da926ba0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/MinecraftScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/MinecraftScreen.java @@ -1,17 +1,27 @@ package com.seibel.distanthorizons.common.wrappers.gui; +#if MC_VER <= MC_1_12_2 +import org.lwjglx.opengl.Display; +#else import com.mojang.blaze3d.platform.Window; - +#endif import com.seibel.distanthorizons.core.config.gui.AbstractScreen; import net.minecraft.client.Minecraft; + +#if MC_VER > MC_1_12_2 import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.screens.Screen; +#endif import org.jetbrains.annotations.NotNull; -#if MC_VER < MC_1_20_1 +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.GuiListExtended; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiSlot; +#elif MC_VER < MC_1_20_1 import com.mojang.blaze3d.vertex.PoseStack; #elif MC_VER <= MC_1_21_11 import net.minecraft.client.gui.GuiGraphics; @@ -24,19 +34,29 @@ import java.util.*; public class MinecraftScreen { + #if MC_VER <= MC_1_12_2 + public static GuiScreen getScreen(GuiScreen parent, AbstractScreen screen, String translationName) + #else public static Screen getScreen(Screen parent, AbstractScreen screen, String translationName) + #endif { return new ConfigScreenRenderer(parent, screen, translationName); } private static class ConfigScreenRenderer extends DhScreen { + #if MC_VER <= MC_1_12_2 + private final GuiScreen parent; + #else private final Screen parent; + #endif private ConfigListWidget configListWidget; private AbstractScreen screen; - - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + public static net.minecraft.util.text.TextComponentTranslation translate(String str, Object... args) + { return new net.minecraft.util.text.TextComponentTranslation(str, args); } + #elif MC_VER < MC_1_19_2 public static net.minecraft.network.chat.TranslatableComponent translate(String str, Object... args) { return new net.minecraft.network.chat.TranslatableComponent(str, args); } #else @@ -44,10 +64,16 @@ public class MinecraftScreen { return net.minecraft.network.chat.Component.translatable(str, args); } #endif + #if MC_VER <= MC_1_12_2 + protected ConfigScreenRenderer(GuiScreen parent, AbstractScreen screen, String translationName) + #else protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName) + #endif { super(translate(translationName)); - #if MC_VER < MC_1_21_9 + #if MC_VER <= MC_1_12_2 + screen.minecraftWindow = Display.getWindow(); + #elif MC_VER < MC_1_21_9 screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow(); #else screen.minecraftWindow = Minecraft.getInstance().getWindow().handle(); @@ -57,30 +83,53 @@ public class MinecraftScreen } @Override + #if MC_VER <= MC_1_12_2 + public void initGui() + #else protected void init() + #endif { - super.init(); // Init Minecraft's screen + #if MC_VER <= MC_1_12_2 + super.initGui(); + #else + super.init(); + #endif + + #if MC_VER <= MC_1_12_2 + this.screen.width = Display.getWidth(); + this.screen.height = Display.getHeight(); + #else Window mcWindow = this.minecraft.getWindow(); this.screen.width = mcWindow.getWidth(); this.screen.height = mcWindow.getHeight(); + #endif this.screen.scaledWidth = this.width; this.screen.scaledHeight = this.height; this.screen.init(); // Init our own config screen + #if MC_VER <= MC_1_12_2 + this.configListWidget = new ConfigListWidget(this.mc, this.width, this.height, 0, 0, 25); // Select the area to tint + #else this.configListWidget = new ConfigListWidget(this.minecraft, this.width, this.height, 0, 0, 25); // Select the area to tint + #endif - #if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+ + #if MC_VER <= MC_1_12_2 + #elif MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+ if (this.minecraft != null && this.minecraft.level != null) // Check if in game { this.configListWidget.setRenderBackground(false); // Disable from rendering } #endif + #if MC_VER > MC_1_12_2 this.addWidget(this.configListWidget); // Add the tint to the things to be rendered + #endif } @Override - #if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + public void drawScreen(int mouseX, int mouseY, float delta) + #elif MC_VER < MC_1_20_1 public void render(PoseStack matrices, int mouseX, int mouseY, float delta) #elif MC_VER <= MC_1_21_11 public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta) @@ -88,7 +137,9 @@ public class MinecraftScreen public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta) #endif { - #if MC_VER < MC_1_20_2 + #if MC_VER <= MC_1_12_2 + this.drawDefaultBackground(); + #elif MC_VER < MC_1_20_2 this.renderBackground(matrices); // Render background #elif MC_VER < MC_1_21_6 this.renderBackground(matrices, mouseX, mouseY, delta); // Render background @@ -96,7 +147,9 @@ public class MinecraftScreen // background blur is already being rendered, rendering again causes the game to crash #endif - #if MC_VER <= MC_1_21_11 + #if MC_VER <= MC_1_12_2 + this.configListWidget.drawScreen(mouseX, mouseY, delta); + #elif MC_VER <= MC_1_21_11 this.configListWidget.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker) #else this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker) @@ -106,55 +159,86 @@ public class MinecraftScreen this.screen.mouseY = mouseY; this.screen.render(delta); // Render everything on the main screen - #if MC_VER <= MC_1_21_11 + #if MC_VER <= MC_1_12_2 + super.drawScreen(mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint) + #elif MC_VER <= MC_1_21_11 super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint) #else super.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker) #endif } - #if MC_VER <= MC_1_21_10 @Override + #if MC_VER <= MC_1_12_2 + public void setWorldAndResolution(Minecraft mc, int width, int height) + #elif MC_VER <= MC_1_21_10 public void resize(Minecraft mc, int width, int height) #else - @Override public void resize(int width, int height) #endif { // Resize Minecraft's screen - #if MC_VER <= MC_1_21_10 + #if MC_VER <= MC_1_12_2 + super.setWorldAndResolution(mc, width, height); + #elif MC_VER <= MC_1_21_10 super.resize(mc, width, height); #else super.resize(width, height); #endif - + #if MC_VER <= MC_1_12_2 + this.screen.width = Display.getWidth(); + this.screen.height = Display.getHeight(); + #else Window mcWindow = this.minecraft.getWindow(); this.screen.width = mcWindow.getWidth(); this.screen.height = mcWindow.getHeight(); + #endif; this.screen.scaledWidth = this.width; this.screen.scaledHeight = this.height; this.screen.onResize(); // Resize our screen } @Override + #if MC_VER <= MC_1_12_2 + public void updateScreen() + #else public void tick() + #endif { + #if MC_VER <= MC_1_12_2 + super.updateScreen(); // Tick Minecraft's screen + #else super.tick(); // Tick Minecraft's screen + #endif + this.screen.tick(); // Tick our screen if (this.screen.close) // If we decide to close the screen, then actually close the screen { + #if MC_VER <= MC_1_12_2 + this.onGuiClosed(); + #else this.onClose(); + #endif } } @Override + #if MC_VER <= MC_1_12_2 + public void onGuiClosed() + #else public void onClose() + #endif { this.screen.onClose(); // Close our screen + #if MC_VER <= MC_1_12_2 + Objects.requireNonNull(this.mc).displayGuiScreen(this.parent); // Goto the parent screen + #else Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Goto the parent screen + #endif } + #if MC_VER > MC_1_12_2 @Override public void onFilesDrop(@NotNull List files) { this.screen.onFilesDrop(files); } @@ -163,10 +247,14 @@ public class MinecraftScreen @Override public boolean shouldCloseOnEsc() { return this.screen.shouldCloseOnEsc; } - + #endif } + #if MC_VER <= MC_1_12_2 + public static class ConfigListWidget extends GuiListExtended + #else public static class ConfigListWidget extends ContainerObjectSelectionList + #endif { public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing) { @@ -178,6 +266,18 @@ public class MinecraftScreen this.centerListVertically = false; } + #if MC_VER <= MC_1_12_2 + @Override + protected int getSize() + { + return 0; + } + @Override + public IGuiListEntry getListEntry(int index) + { + return null; + } + #endif } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/OnPressed.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/OnPressed.java new file mode 100644 index 000000000..3227ab477 --- /dev/null +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/OnPressed.java @@ -0,0 +1,9 @@ +package com.seibel.distanthorizons.common.wrappers.gui; + +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.GuiButton; + +public interface OnPressed { + void pressed(GuiButton button); +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/TexturedButtonWidget.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/TexturedButtonWidget.java index f51f5fe3d..5609f5749 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/TexturedButtonWidget.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/TexturedButtonWidget.java @@ -19,13 +19,21 @@ package com.seibel.distanthorizons.common.wrappers.gui; +#if MC_VER > MC_1_12_2 import net.minecraft.network.chat.Component; +#endif #if MC_VER >= MC_1_17_1 import net.minecraft.client.gui.components.Button; #endif -#if MC_VER < MC_1_17_1 + +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; +#elif MC_VER < MC_1_17_1 import net.minecraft.client.gui.components.ImageButton; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; @@ -53,7 +61,9 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.renderer.RenderPipelines; #endif -#if MC_VER <= MC_1_21_10 +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.ResourceLocation; +#elif MC_VER <= MC_1_21_10 import net.minecraft.resources.ResourceLocation; #else import net.minecraft.resources.Identifier; @@ -65,7 +75,10 @@ import net.minecraft.resources.Identifier; * @author coolGi * @version 2023-10-03 */ -#if MC_VER < MC_1_20_2 +#if MC_VER <= MC_1_12_2 +@SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions) +public class TexturedButtonWidget extends GuiButton +#elif MC_VER < MC_1_20_2 @SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions) public class TexturedButtonWidget extends ImageButton #else @@ -75,7 +88,7 @@ public class TexturedButtonWidget extends Button { public final boolean renderBackground; - #if MC_VER >= MC_1_20_2 + #if MC_VER >= MC_1_20_2 || MC_VER <= MC_1_12_2 private final int u; private final int v; private final int hoveredVOffset; @@ -90,30 +103,41 @@ public class TexturedButtonWidget extends Button private final int textureHeight; #endif - - public TexturedButtonWidget( - int x, int y, int width, int height, int u, int v, int hoveredVOffset, - #if MC_VER <= MC_1_21_10 ResourceLocation textureResourceLocation, - #else Identifier textureResourceLocation, - #endif - int textureWidth, int textureHeight, OnPress pressAction, Component text) + #if MC_VER <= MC_1_12_2 + public TexturedButtonWidget(int id, int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, String text) + { + this(id, x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, text, true); + } + #elif MC_VER <= MC_1_21_10 + public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text) { this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true); } - public TexturedButtonWidget( - int x, int y, int width, int height, int u, int v, int hoveredVOffset, - #if MC_VER <= MC_1_21_10 ResourceLocation textureResourceLocation, - #else Identifier textureResourceLocation, - #endif - int textureWidth, int textureHeight, OnPress pressAction, Component text, - boolean renderBackground) + #else + public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text) { - #if MC_VER < MC_1_20_2 + this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true); + } + #endif + + #if MC_VER <= MC_1_12_2 + public TexturedButtonWidget(int id, int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, String text, boolean renderBackground) + #elif MC_VER <= MC_1_21_10 + public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground) + #else + public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground) + #endif + { + #if MC_VER <= MC_1_12_2 + super(id, x, y, width, height, text); + #elif MC_VER < MC_1_20_2 super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text); #else // We don't pass in the text option since it will render (we normally pass it in for narration) super(x, y, width, height, Component.empty(), pressAction, DEFAULT_NARRATION); + #endif + #if MC_VER >= MC_1_20_2 || MC_VER <= MC_1_12_2 this.u = u; this.v = v; this.hoveredVOffset = hoveredVOffset; @@ -127,7 +151,27 @@ public class TexturedButtonWidget extends Button this.renderBackground = renderBackground; } - #if MC_VER < MC_1_20_2 + #if MC_VER <= MC_1_12_2 + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) { + if (this.visible) { + //Render vanilla background + mc.getTextureManager().bindTexture(BUTTON_TEXTURES); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; + int i = this.getHoverState(this.hovered); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + this.drawTexturedModalRect(this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height); + this.drawTexturedModalRect(this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height); + + //Render DH texture + mc.getTextureManager().bindTexture(textureResourceLocation); + drawModalRectWithCustomSizedTexture(this.x, this.y, this.u, (hoveredVOffset * (i - 1)), this.width, this.height, this.textureWidth, this.textureHeight); + } + } + #elif MC_VER < MC_1_20_2 #if MC_VER < MC_1_19_4 @Override public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/ClassicConfigGUI.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/ClassicConfigGUI.java index fad8baa43..7ca4dfaa4 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/ClassicConfigGUI.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/ClassicConfigGUI.java @@ -12,17 +12,24 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosi import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui; import net.minecraft.client.Minecraft; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.*; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.text.ITextComponent; +#else import net.minecraft.client.gui.Font; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +#endif import com.seibel.distanthorizons.core.logging.DhLogger; + import org.jetbrains.annotations.NotNull; - -#if MC_VER < MC_1_20_1 +#if MC_VER <= MC_1_12_2 +#elif MC_VER < MC_1_20_1 import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.GuiComponent; #elif MC_VER <= MC_1_21_11 @@ -67,6 +74,7 @@ public class ClassicConfigGUI //==============// // Initializers // //==============// + //region // Some regexes to check if an input is valid public static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)"); @@ -87,25 +95,46 @@ public class ClassicConfigGUI } + //endregion + //==============// // GUI handling // //==============// - + //region /** if you want to get this config gui's screen call this */ + #if MC_VER <= MC_1_12_2 + public static GuiScreen getScreen(GuiScreen parent, String category) + #else public static Screen getScreen(Screen parent, String category) + #endif { return new DhConfigScreen(parent, category); } + //endregion + //================// // helper classes // //================// + //region + #if MC_VER <= MC_1_12_2 + public static class ConfigListWidget extends GuiListExtended + #else public static class ConfigListWidget extends ContainerObjectSelectionList + #endif { + #if MC_VER <= MC_1_12_2 + public List children = new ArrayList<>(); + #endif + + #if MC_VER <= MC_1_12_2 + FontRenderer textRenderer; + #else Font textRenderer; + #endif public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing) { @@ -116,40 +145,121 @@ public class ClassicConfigGUI #endif this.centerListVertically = false; + #if MC_VER <= MC_1_12_2 + this.textRenderer = minecraftClient.fontRenderer; + #else this.textRenderer = minecraftClient.font; + #endif } - public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text) - { this.addEntry(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton)); } + #if MC_VER <= MC_1_12_2 + @Override + protected int getSize() + { + return this.children.size(); + } @Override - public int getRowWidth() { return 10_000; } - - public AbstractWidget getHoveredButton(double mouseX, double mouseY) + public IGuiListEntry getListEntry(int index) { - for (DhButtonEntry buttonEntry : this.children()) + return this.children.get(index); + } + + @Override + protected void drawContainerBackground(Tessellator tessellator) + { + if (this.mc.world != null) { - AbstractWidget button = buttonEntry.button; - if (button != null - && button.visible) + return; // in-game don't draw dirt background + } + super.drawContainerBackground(tessellator); + } + #endif + + #if MC_VER <= MC_1_12_2 + public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, Gui button, GuiButton resetButton, GuiButton indexButton, ITextComponent text) + #else + public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text) + #endif + { + #if MC_VER <= MC_1_12_2 + this.children.add(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton)); + #else + this.addEntry(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton)); + #endif + } + + @Override + #if MC_VER <= MC_1_12_2 + public int getListWidth() + #else + public int getRowWidth() + #endif + { return 10_000; } + + #if MC_VER <= MC_1_12_2 + public Gui getHoveredButton(double mouseX, double mouseY) + #else + public AbstractWidget getHoveredButton(double mouseX, double mouseY) + #endif + { + #if MC_VER <= MC_1_12_2 + for (DhButtonEntry buttonEntry : this.children) + #else + for (DhButtonEntry buttonEntry : this.children()) + #endif + { + #if MC_VER <= MC_1_12_2 + Gui gui = buttonEntry.button; + if (gui == null) continue; + + double minX, minY, maxX, maxY; + + if (gui instanceof GuiButton button) { - #if MC_VER < MC_1_19_4 - double minX = button.x; - double minY = button.y; - #else - double minX = button.getX(); - double minY = button.getY(); - #endif - - double maxX = minX + button.getWidth(); - double maxY = minY + button.getHeight(); - - if (mouseX >= minX && mouseX < maxX - && mouseY >= minY && mouseY < maxY) - { - return button; - } + if (!button.visible) continue; + minX = button.x; + minY = button.y; + maxX = minX + button.width; + maxY = minY + button.height; } + else if (gui instanceof GuiTextField field) + { + if (!field.getVisible()) continue; + minX = field.x; + minY = field.y; + maxX = minX + field.width; + maxY = minY + field.height; + } + else + { + continue; + } + + if (mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY) + { + return gui; + } + #else + AbstractWidget button = (AbstractWidget) buttonEntry.button; + if (button == null || !button.visible) continue; + + #if MC_VER < MC_1_19_4 + double minX = button.x; + double minY = button.y; + #else + double minX = button.getX(); + double minY = button.getY(); + #endif + + double maxX = minX + button.getWidth(); + double maxY = minY + button.getHeight(); + + if (mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY) + { + return button; + } + #endif } return null; @@ -157,32 +267,60 @@ public class ClassicConfigGUI } - + #if MC_VER <= MC_1_12_2 + public static class DhButtonEntry implements GuiListExtended.IGuiListEntry + #else public static class DhButtonEntry extends ContainerObjectSelectionList.Entry + #endif { + #if MC_VER <= MC_1_12_2 + private static final FontRenderer textRenderer = Minecraft.getMinecraft().fontRenderer; + #else private static final Font textRenderer = Minecraft.getInstance().font; - - private final AbstractWidget button; + #endif private final DhConfigScreen gui; - - private final AbstractWidget resetButton; + #if MC_VER <= MC_1_12_2 + public final Gui button; + public final Gui resetButton; + public final Gui indexButton; + #else private final AbstractWidget indexButton; + private final AbstractWidget resetButton; + private final AbstractWidget button; + #endif + + #if MC_VER <= MC_1_12_2 + private final ITextComponent text; + #else private final Component text; + #endif + + #if MC_VER <= MC_1_12_2 + private final List children = new ArrayList<>(); + #else private final List children = new ArrayList<>(); + #endif @NotNull private final EConfigCommentTextPosition textPosition; public final AbstractConfigBase dhConfigType; + #if MC_VER <= MC_1_12_2 + public static final Map TEXT_BY_WIDGET = new HashMap<>(); + public static final Map BUTTON_BY_WIDGET = new HashMap<>(); + #else public static final Map TEXT_BY_WIDGET = new HashMap<>(); public static final Map BUTTON_BY_WIDGET = new HashMap<>(); + #endif - public DhButtonEntry( - DhConfigScreen gui, AbstractConfigBase dhConfigType, - AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) + #if MC_VER <= MC_1_12_2 + public DhButtonEntry(DhConfigScreen gui, AbstractConfigBase dhConfigType, Gui button, ITextComponent text, GuiButton resetButton, GuiButton indexButton) + #else + public DhButtonEntry(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) + #endif { TEXT_BY_WIDGET.put(button, text); BUTTON_BY_WIDGET.put(button, this); @@ -225,7 +363,9 @@ public class ClassicConfigGUI @Override - #if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float tickDelta) + #elif MC_VER < MC_1_20_1 public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) #elif MC_VER < MC_1_21_9 public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) @@ -250,18 +390,40 @@ public class ClassicConfigGUI if (this.button != null) { - SetY(this.button, y); - #if MC_VER <= MC_1_21_11 - this.button.render(matrices, mouseX, mouseY, tickDelta); + #if MC_VER <= MC_1_12_2 + if (this.button instanceof GuiButton guiButton) + { + SetY(guiButton, y); + guiButton.drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta); + } + if (this.button instanceof GuiTextField guiTextField) + { + SetY(guiTextField, y); + guiTextField.drawTextBox(); + } #else - this.button.extractRenderState(matrices, mouseX, mouseY, tickDelta); + SetY(this.button, y); + { + #if MC_VER <= MC_1_21_11 + this.button.render(matrices, mouseX, mouseY, tickDelta); + #else + this.button.extractRenderState(matrices, mouseX, mouseY, tickDelta); + #endif + } #endif } if (this.resetButton != null) { + #if MC_VER <= MC_1_12_2 + SetY((GuiButton) this.resetButton, y); + #else SetY(this.resetButton, y); - #if MC_VER <= MC_1_21_11 + #endif + + #if MC_VER <= MC_1_12_2 + ((GuiButton) this.resetButton).drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta); + #elif MC_VER <= MC_1_21_11 this.resetButton.render(matrices, mouseX, mouseY, tickDelta); #else this.resetButton.extractRenderState(matrices, mouseX, mouseY, tickDelta); @@ -270,8 +432,15 @@ public class ClassicConfigGUI if (this.indexButton != null) { + #if MC_VER <= MC_1_12_2 + SetY((GuiButton) this.indexButton, y); + #else SetY(this.indexButton, y); - #if MC_VER <= MC_1_21_11 + #endif + + #if MC_VER <= MC_1_12_2 + ((GuiButton) this.indexButton).drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta); + #elif MC_VER <= MC_1_21_11 this.indexButton.render(matrices, mouseX, mouseY, tickDelta); #else this.indexButton.extractRenderState(matrices, mouseX, mouseY, tickDelta); @@ -280,7 +449,11 @@ public class ClassicConfigGUI if (this.text != null) { + #if MC_VER <= MC_1_12_2 + int translatedLength = textRenderer.getStringWidth(this.text.getFormattedText()); + #else int translatedLength = textRenderer.width(this.text); + #endif int textXPos; if (this.textPosition == EConfigCommentTextPosition.RIGHT_JUSTIFIED) @@ -313,17 +486,21 @@ public class ClassicConfigGUI throw new UnsupportedOperationException("No text position render defined for [" + this.textPosition + "]"); } - - #if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + textRenderer.drawString( + this.text.getFormattedText(), + textXPos, y + 5, + 0xFFFFFF); + #elif MC_VER < MC_1_20_1 GuiComponent.drawString(matrices, textRenderer, - this.text, - textXPos, y + 5, - 0xFFFFFF); + this.text, + textXPos, y + 5, + 0xFFFFFF); #elif MC_VER < MC_1_21_6 - matrices.drawString(textRenderer, - this.text, - textXPos, y + 5, - 0xFFFFFF); + matrices.drawString(textRenderer, + this.text, + textXPos, y + 5, + 0xFFFFFF); #elif MC_VER <= MC_1_21_11 matrices.drawString(textRenderer, this.text, @@ -344,9 +521,25 @@ public class ClassicConfigGUI } } + #if MC_VER <= MC_1_12_2 + @Override + public void updatePosition(int slotIndex, int x, int y, float partialTicks) { } + + @Override + public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) + { + return false; // handled in DhConfigScreen.mouseClicked + } + + @Override + public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) { } + #endif + + #if MC_VER > MC_1_12_2 @Override public @NotNull List children() { return this.children; } + #endif #if MC_VER >= MC_1_17_1 @Override @@ -358,11 +551,14 @@ public class ClassicConfigGUI } + //endregion + //================// // event handling // //================// + //region public static class ConfigCoreInterface implements IConfigGui { @@ -381,4 +577,5 @@ public class ClassicConfigGUI } + //endregion } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/DhConfigScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/DhConfigScreen.java index c5c4a110a..073b6b242 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/DhConfigScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/classicConfig/DhConfigScreen.java @@ -13,14 +13,18 @@ import java.util.regex.Pattern; import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui; import com.seibel.distanthorizons.common.wrappers.gui.DhScreen; +import com.seibel.distanthorizons.common.wrappers.gui.GuiHelper; import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; import com.seibel.distanthorizons.common.wrappers.gui.config.ConfigGuiInfo; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.ConfigHandler; import com.seibel.distanthorizons.core.config.types.*; +#if MC_VER <= MC_1_12_2 +import com.seibel.distanthorizons.common.wrappers.gui.OnPressed; +#else import com.seibel.distanthorizons.common.wrappers.gui.updater.ChangelogScreen; - +#endif import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosition; import com.seibel.distanthorizons.core.config.types.enums.EConfigValidity; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -30,8 +34,15 @@ import com.seibel.distanthorizons.core.util.AnnotationUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; -import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.gui.*; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextFormatting; +#else +import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; @@ -40,12 +51,13 @@ import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +#endif import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; - -#if MC_VER < MC_1_20_1 +#if MC_VER <= MC_1_12_2 +#elif MC_VER < MC_1_20_1 import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.GuiComponent; #elif MC_VER <= MC_1_21_11 @@ -58,14 +70,18 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.narration.NarratableEntry; #endif -#if MC_VER <= MC_1_21_10 +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.ResourceLocation; +#elif MC_VER <= MC_1_21_10 import net.minecraft.resources.ResourceLocation; #else import net.minecraft.resources.Identifier; #endif import org.lwjgl.glfw.GLFW; +#if MC_VER > MC_1_12_2 import com.mojang.blaze3d.platform.InputConstants; +#endif import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*; import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translatable; @@ -79,21 +95,34 @@ class DhConfigScreen extends DhScreen private static final MinecraftClientWrapper MC_CLIENT = MinecraftClientWrapper.INSTANCE; - + #if MC_VER <= MC_1_12_2 + private final GuiScreen parent; + #else private final Screen parent; + #endif + private final String category; private ClassicConfigGUI.ConfigListWidget configListWidget; private boolean reload = false; + #if MC_VER <= MC_1_12_2 + private GuiButton doneButton; + #else private Button doneButton; + #endif //=============// // constructor // //=============// + //region + #if MC_VER <= MC_1_12_2 + protected DhConfigScreen(GuiScreen parent, String category) + #else protected DhConfigScreen(Screen parent, String category) + #endif { super(Translatable( LANG_WRAPPER.langExists(ModInfo.ID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ? @@ -104,25 +133,50 @@ class DhConfigScreen extends DhScreen this.category = category; } + //endregion + + + //===================// + // menu UI lifecycle // + //===================// + //region + @Override + #if MC_VER <= MC_1_12_2 + public void updateScreen() { super.updateScreen(); } + #else public void tick() { super.tick(); } + #endif - - + //endregion + + + //==================// // menu UI creation // //==================// + //region @Override + #if MC_VER <= MC_1_12_2 + public void initGui() + #else protected void init() + #endif { + #if MC_VER <= MC_1_12_2 + super.initGui(); + #else super.init(); + #endif + if (!this.reload) { ConfigHandler.INSTANCE.configFileHandler.loadFromFile(); } + #if MC_VER > MC_1_12_2 // Changelog button if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get() // we only have changelogs for stable builds @@ -161,6 +215,7 @@ class DhConfigScreen extends DhScreen Translatable(ModInfo.ID + ".updater.title") )); } + #endif // back button @@ -170,7 +225,11 @@ class DhConfigScreen extends DhScreen (button) -> { ConfigHandler.INSTANCE.configFileHandler.loadFromFile(); + #if MC_VER <= MC_1_12_2 + Objects.requireNonNull(this.mc).displayGuiScreen(this.parent); + #else Objects.requireNonNull(this.minecraft).setScreen(this.parent); + #endif })); // done/close button @@ -181,19 +240,30 @@ class DhConfigScreen extends DhScreen (button) -> { ConfigHandler.INSTANCE.configFileHandler.saveToFile(); + #if MC_VER <= MC_1_12_2 + Objects.requireNonNull(this.mc).displayGuiScreen(this.parent); + #else Objects.requireNonNull(this.minecraft).setScreen(this.parent); + #endif })); + #if MC_VER <= MC_1_12_2 + this.configListWidget = new ClassicConfigGUI.ConfigListWidget(this.mc, this.width * 2, this.height, 32, 32, 25); + #else this.configListWidget = new ClassicConfigGUI.ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, 32, 25); + #endif - #if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+ + #if MC_VER <= MC_1_12_2 + #elif MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+ if (this.minecraft != null && this.minecraft.level != null) { this.configListWidget.setRenderBackground(false); } #endif + #if MC_VER > MC_1_12_2 this.addWidget(this.configListWidget); + #endif for (AbstractConfigBase configEntry : ConfigHandler.INSTANCE.configBaseList) { @@ -356,18 +426,35 @@ class DhConfigScreen extends DhScreen private static void setupBooleanMenuOption(ConfigEntry booleanConfigEntry) { // For boolean + #if MC_VER <= MC_1_12_2 + Function func = value -> Translatable("distanthorizons.general."+((Boolean) value ? "true" : "false")).setStyle(new Style().setColor((Boolean) value ? TextFormatting.GREEN : TextFormatting.RED)); + #else Function func = value -> Translatable("distanthorizons.general." + ((Boolean) value ? "true" : "false")).withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED); + #endif final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) booleanConfigEntry.guiValue); configGuiInfo.buttonOptionMap = + #if MC_VER <= MC_1_12_2 + new AbstractMap.SimpleEntry>( + #else new AbstractMap.SimpleEntry>( + #endif (button) -> { + #if MC_VER <= MC_1_12_2 + button.enabled = !booleanConfigEntry.apiIsOverriding(); + #else button.active = !booleanConfigEntry.apiIsOverriding(); - + #endif + booleanConfigEntry.uiSetWithoutSaving(!booleanConfigEntry.get()); + + #if MC_VER <= MC_1_12_2 + button.displayString = func.apply(booleanConfigEntry.get()).getFormattedText(); + #else button.setMessage(func.apply(booleanConfigEntry.get())); + #endif }, func); } private static void setupEnumMenuOption(ConfigEntry> enumConfigEntry, Class> enumClass) @@ -376,20 +463,29 @@ class DhConfigScreen extends DhScreen final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) enumConfigEntry.guiValue); + #if MC_VER <= MC_1_12_2 + Function getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString()); + #else Function getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString()); + #endif + configGuiInfo.buttonOptionMap = + #if MC_VER <= MC_1_12_2 + new AbstractMap.SimpleEntry>( + #else new AbstractMap.SimpleEntry>( + #endif (button) -> { // get the currently selected enum and enum index int startingIndex = enumList.indexOf(enumConfigEntry.get()); Enum enumValue = enumList.get(startingIndex); - boolean shiftPressed = - InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_LEFT_SHIFT) - || InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_RIGHT_SHIFT); - - + #if MC_VER <= MC_1_12_2 + boolean shiftPressed = GuiScreen.isShiftKeyDown(); + #else + boolean shiftPressed = InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_RIGHT_SHIFT); + #endif // move forward or backwards depending on if the shift key is pressed int index = shiftPressed ? startingIndex - 1 : startingIndex + 1; @@ -441,9 +537,13 @@ class DhConfigScreen extends DhScreen enumConfigEntry.uiSetWithoutSaving(enumValue); + #if MC_VER <= MC_1_12_2 + button.enabled = !enumConfigEntry.apiIsOverriding(); + button.displayString = getEnumTranslatableFunc.apply(enumConfigEntry.get()).getFormattedText(); + #else button.active = !enumConfigEntry.apiIsOverriding(); - button.setMessage(getEnumTranslatableFunc.apply(enumConfigEntry.get())); + #endif }, getEnumTranslatableFunc); } @@ -459,12 +559,17 @@ class DhConfigScreen extends DhScreen //==============// // reset button // //==============// + //region - Button.OnPress btnAction = (button) -> + #if MC_VER <= MC_1_12_2 OnPressed #else Button.OnPress #endif btnAction = (button) -> { configEntry.uiSetWithoutSaving(configEntry.getDefaultValue()); this.reload = true; - Objects.requireNonNull(this.minecraft).setScreen(this); + #if MC_VER <= MC_1_12_2 + Objects.requireNonNull(this.mc).displayGuiScreen(ClassicConfigGUI.getScreen(this.parent, this.category)); + #else + Objects.requireNonNull(this.minecraft).setScreen(this.parent); + #endif }; int resetButtonPosX = this.width @@ -472,29 +577,45 @@ class DhConfigScreen extends DhScreen - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN; int resetButtonPosZ = 0; - Button resetButton = MakeBtn( + #if MC_VER <= MC_1_12_2 GuiButton #else Button #endif resetButton = MakeBtn( + #if MC_VER <= MC_1_12_2 + Translatable("distanthorizons.general.reset").setStyle(new Style().setColor(TextFormatting.RED)), + #else Translatable("distanthorizons.general.reset").withStyle(ChatFormatting.RED), + #endif resetButtonPosX, resetButtonPosZ, ClassicConfigGUI.ConfigScreenConfigs.RESET_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.RESET_BUTTON_HEIGHT, btnAction); if (configEntry.apiIsOverriding()) { + #if MC_VER <= MC_1_12_2 + resetButton.enabled = false; + resetButton.displayString = Translatable("distanthorizons.general.apiOverride").setStyle(new Style().setColor(TextFormatting.DARK_GRAY)).getFormattedText(); + #else resetButton.active = false; resetButton.setMessage(Translatable("distanthorizons.general.apiOverride").withStyle(ChatFormatting.DARK_GRAY)); + #endif } else { - resetButton.active = true; + resetButton.#if MC_VER <= MC_1_12_2 enabled #else active #endif = true; } - + //endregion + + //==============// // option field // //==============// + //region + #if MC_VER <= MC_1_12_2 + ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configEntry); + #else Component textComponent = this.GetTranslatableTextComponentForConfig(configEntry); + #endif int optionFieldPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN @@ -506,22 +627,33 @@ class DhConfigScreen extends DhScreen if (configGuiInfo.buttonOptionMap != null) { // enum/multi option input button - + #if MC_VER <= MC_1_12_2 + Map.Entry> widget = configGuiInfo.buttonOptionMap; + #else Map.Entry> widget = configGuiInfo.buttonOptionMap; + #endif + if (configEntry.getType().isEnum()) { widget.setValue((value) -> Translatable(TRANSLATION_PREFIX + "enum." + configEntry.getType().getSimpleName() + "." + configEntry.get().toString())); } + #if MC_VER <= MC_1_12_2 + GuiButton button = MakeBtn( + #else Button button = MakeBtn( + #endif widget.getValue().apply(configEntry.get()), optionFieldPosX, optionFieldPosZ, ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, widget.getKey()); // deactivate the button if the API is overriding it + #if MC_VER <= MC_1_12_2 + button.enabled = !configEntry.apiIsOverriding(); + #else button.active = !configEntry.apiIsOverriding(); - + #endif this.configListWidget.addButton(this, configEntry, button, @@ -534,16 +666,25 @@ class DhConfigScreen extends DhScreen else { // text box input - + #if MC_VER <= MC_1_12_2 + GuiTextField widget = new GuiTextField(0, this.fontRenderer, + optionFieldPosX, optionFieldPosZ, + ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH - 4, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT); + widget.setMaxStringLength(3_000_000); // hopefully 3 million characters should be enough for any normal use-case, lol + widget.setText(String.valueOf(configEntry.get())); + #else EditBox widget = new EditBox(this.font, optionFieldPosX, optionFieldPosZ, ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH - 4, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, Translatable("")); widget.setMaxLength(3_000_000); // hopefully 3 million characters should be enough for any normal use-case, lol widget.insertText(String.valueOf(configEntry.get())); + #endif Predicate processor = configGuiInfo.tooltipFunction.apply(widget, this.doneButton); - #if MC_VER <= MC_1_21_11 + #if MC_VER <= MC_1_12_2 + widget.setValidator(processor::test); + #elif MC_VER <= MC_1_21_11 widget.setFilter(processor); #else widget.setResponder(processor::test); @@ -553,6 +694,8 @@ class DhConfigScreen extends DhScreen return true; } + + //endregion } return false; @@ -563,18 +706,31 @@ class DhConfigScreen extends DhScreen { ConfigCategory configCategory = (ConfigCategory) configType; + #if MC_VER <= MC_1_12_2 + ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configCategory); + #else Component textComponent = this.GetTranslatableTextComponentForConfig(configCategory); + #endif int categoryPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN; int categoryPosZ = this.height - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT; // Note: the posZ value here seems to be ignored - Button widget = MakeBtn(textComponent, + #if MC_VER <= MC_1_12_2 + GuiButton widget = MakeBtn( + #else + Button widget = MakeBtn( + #endif + textComponent, categoryPosX, categoryPosZ, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, ((button) -> { ConfigHandler.INSTANCE.configFileHandler.saveToFile(); + #if MC_VER <= MC_1_12_2 + Objects.requireNonNull(this.mc).displayGuiScreen(ClassicConfigGUI.getScreen(this, configCategory.getDestination())); + #else Objects.requireNonNull(this.minecraft).setScreen(ClassicConfigGUI.getScreen(this, configCategory.getDestination())); + #endif })); this.configListWidget.addButton(this, configType, widget, null, null, null); @@ -589,11 +745,20 @@ class DhConfigScreen extends DhScreen { ConfigUIButton configUiButton = (ConfigUIButton) configType; + #if MC_VER <= MC_1_12_2 + ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configUiButton); + #else Component textComponent = this.GetTranslatableTextComponentForConfig(configUiButton); + #endif int buttonPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN; - Button widget = MakeBtn(textComponent, + #if MC_VER <= MC_1_12_2 + GuiButton widget = MakeBtn( + #else + Button widget = MakeBtn( + #endif + textComponent, buttonPosX, this.height - 28, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, (button) -> ((ConfigUIButton) configType).runAction()); @@ -610,7 +775,11 @@ class DhConfigScreen extends DhScreen { ConfigUIComment configUiComment = (ConfigUIComment) configType; + #if MC_VER <= MC_1_12_2 + ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configUiComment); + #else Component textComponent = this.GetTranslatableTextComponentForConfig(configUiComment); + #endif if (configUiComment.parentConfigPath != null) { textComponent = Translatable(TRANSLATION_PREFIX + configUiComment.parentConfigPath); @@ -626,8 +795,13 @@ class DhConfigScreen extends DhScreen private boolean tryCreateSpacer(AbstractConfigBase configType) { if (configType instanceof ConfigUISpacer) - { - Button spacerButton = MakeBtn(Translatable("distanthorizons.general.spacer"), + { + #if MC_VER <= MC_1_12_2 + GuiButton spacerButton = MakeBtn( + #else + Button spacerButton = MakeBtn( + #endif + Translatable("distanthorizons.general.spacer"), 10, 10, // having too small of a size causes division by 0 errors in older MC versions (IE 1.20.1) 1, 1, (button) -> { }); @@ -652,25 +826,36 @@ class DhConfigScreen extends DhScreen return false; } + #if MC_VER <= MC_1_12_2 + private ITextComponent GetTranslatableTextComponentForConfig(AbstractConfigBase configType) + #else private Component GetTranslatableTextComponentForConfig(AbstractConfigBase configType) + #endif { return Translatable(TRANSLATION_PREFIX + configType.getNameAndCategory()); } + //endregion + //===========// // rendering // //===========// + //region @Override -#if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + public void drawScreen(int mouseX, int mouseY, float delta) + #elif MC_VER < MC_1_20_1 public void render(PoseStack matrices, int mouseX, int mouseY, float delta) -#elif MC_VER <= MC_1_21_11 + #elif MC_VER <= MC_1_21_11 public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta) -#else + #else public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta) #endif { - #if MC_VER < MC_1_20_2 // 1.20.2 now enables this by default in the `this.list.render` function + #if MC_VER <= MC_1_12_2 + this.drawDefaultBackground(); + #elif MC_VER < MC_1_20_2 // 1.20.2 now enables this by default in the `this.list.render` function this.renderBackground(matrices); #elif MC_VER <= MC_1_21_11 super.render(matrices, mouseX, mouseY, delta); @@ -679,7 +864,9 @@ class DhConfigScreen extends DhScreen #endif // Render buttons - #if MC_VER <= MC_1_21_11 + #if MC_VER <= MC_1_12_2 + this.configListWidget.drawScreen(mouseX, mouseY, delta); + #elif MC_VER <= MC_1_21_11 this.configListWidget.render(matrices, mouseX, mouseY, delta); #else this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta); @@ -687,51 +874,74 @@ class DhConfigScreen extends DhScreen // Render config title - this.DhDrawCenteredString(matrices, this.font, this.title, + this.DhDrawCenteredString( + #if MC_VER > MC_1_12_2 + matrices, this.font, + #endif + this.title, this.width / 2, 15, - #if MC_VER < MC_1_21_6 + #if MC_VER < MC_1_21_6 0xFFFFFF // RGB white - #else - 0xFFFFFFFF // ARGB white - #endif ); + #else + 0xFFFFFFFF // ARGB white + #endif); // render DH version - this.DhDrawString(matrices, this.font, TextOrLiteral(ModInfo.VERSION), 2, this.height - 10, - #if MC_VER < MC_1_21_6 + this.DhDrawString( + #if MC_VER > MC_1_12_2 + matrices, this.font, + #endif + TextOrLiteral(ModInfo.VERSION), 2, this.height - 10, + #if MC_VER < MC_1_21_6 0xAAAAAA // RGB white - #else - 0xFFAAAAAA // ARGB white - #endif ); + #else + 0xFFAAAAAA // ARGB white + #endif); // If the update is pending, display this message to inform the user that it will apply when the game restarts if (SelfUpdater.deleteOldJarOnJvmShutdown) { - this.DhDrawString(matrices, this.font, Translatable(ModInfo.ID + ".updater.waitingForClose"), 4, this.height - 42, - #if MC_VER < MC_1_21_6 + this.DhDrawString( + #if MC_VER > MC_1_12_2 + matrices, this.font, + #endif + Translatable(ModInfo.ID + ".updater.waitingForClose"), 4, this.height - 42, + #if MC_VER < MC_1_21_6 0xFFFFFF // RGB white - #else - 0xFFFFFFFF // ARGB white - #endif ); + #else + 0xFFFFFFFF // ARGB white + #endif); } - + #if MC_VER <= MC_1_12_2 + this.renderTooltip(mouseX, mouseY, delta); + #else this.renderTooltip(matrices, mouseX, mouseY, delta); + #endif - #if MC_VER < MC_1_20_2 + #if MC_VER <= MC_1_12_2 + super.drawScreen(mouseX, mouseY, delta); + #elif MC_VER < MC_1_20_2 super.render(matrices, mouseX, mouseY, delta); #endif } - #if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + private void renderTooltip(int mouseX, int mouseY, float delta) + #elif MC_VER < MC_1_20_1 private void renderTooltip(PoseStack matrices, int mouseX, int mouseY, float delta) #elif MC_VER <= MC_1_21_11 private void renderTooltip(GuiGraphics matrices, int mouseX, int mouseY, float delta) -#else + #else private void renderTooltip(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta) #endif { + #if MC_VER <= MC_1_12_2 + Gui hoveredWidget = this.configListWidget.getHoveredButton(mouseX, mouseY); + #else AbstractWidget hoveredWidget = this.configListWidget.getHoveredButton(mouseX, mouseY); + #endif if (hoveredWidget == null) { return; @@ -763,37 +973,116 @@ class DhConfigScreen extends DhScreen final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) configBase.guiValue); if (configGuiInfo.errorMessage != null) { + #if MC_VER <= MC_1_12_2 + this.DhRenderTooltip(configGuiInfo.errorMessage, mouseX, mouseY); + #else this.DhRenderTooltip(matrices, this.font, configGuiInfo.errorMessage, mouseX, mouseY); + #endif } // display the tooltip if present else if (LANG_WRAPPER.langExists(key)) { + #if MC_VER <= MC_1_12_2 + List list = new ArrayList<>(); + #else List list = new ArrayList<>(); + #endif + String lang = LANG_WRAPPER.getLang(key); for (String langLine : lang.split("\n")) { list.add(TextOrTranslatable(langLine)); } + #if MC_VER <= MC_1_12_2 + this.DhRenderComponentTooltip(list, mouseX, mouseY); + #else this.DhRenderComponentTooltip(matrices, this.font, list, mouseX, mouseY); + #endif } } + #if MC_VER <= MC_1_12_2 + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws java.io.IOException + { + super.mouseClicked(mouseX, mouseY, mouseButton); + + if (mouseY >= this.configListWidget.top && mouseY <= this.configListWidget.bottom) + { + for (ClassicConfigGUI.DhButtonEntry entry : this.configListWidget.children) + { + if (entry.button instanceof GuiButton btn && btn.visible) + { + if (btn.mousePressed(this.mc, mouseX, mouseY)) + { + btn.playPressSound(this.mc.getSoundHandler()); + OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(btn); + if (handler != null) handler.pressed(btn); + } + } + else if (entry.button instanceof GuiTextField field && field.getVisible()) + { + field.mouseClicked(mouseX, mouseY, mouseButton); + } + + if (entry.resetButton instanceof GuiButton reset && reset.visible) + { + if (reset.mousePressed(this.mc, mouseX, mouseY)) + { + reset.playPressSound(this.mc.getSoundHandler()); + OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(reset); + if (handler != null) handler.pressed(reset); + } + } + } + } + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws java.io.IOException + { + super.keyTyped(typedChar, keyCode); + for (ClassicConfigGUI.DhButtonEntry entry : this.configListWidget.children) + { + if (entry.button instanceof GuiTextField field) + { + field.textboxKeyTyped(typedChar, keyCode); + } + } + } + + @Override + public void handleMouseInput() throws java.io.IOException + { + super.handleMouseInput(); + this.configListWidget.handleMouseInput(); + } + #endif + + //endregion + //==========// // shutdown // //==========// - + //region /** When you close it, it goes to the previous screen and saves */ @Override + #if MC_VER <= MC_1_12_2 + public void onGuiClosed() + #else public void onClose() + #endif { ConfigHandler.INSTANCE.configFileHandler.saveToFile(); + #if MC_VER > MC_1_12_2 Objects.requireNonNull(this.minecraft).setScreen(this.parent); - + #endif ClassicConfigGUI.CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run()); } + //endregion } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/config/ConfigGuiInfo.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/config/ConfigGuiInfo.java index ad29c4a0c..131f2f548 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/config/ConfigGuiInfo.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/config/ConfigGuiInfo.java @@ -2,9 +2,16 @@ package com.seibel.distanthorizons.common.wrappers.gui.config; import com.seibel.distanthorizons.core.config.gui.IConfigGuiInfo; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase; +#if MC_VER <= MC_1_12_2 +import com.seibel.distanthorizons.common.wrappers.gui.OnPressed; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.util.text.ITextComponent; +#else import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; import net.minecraft.network.chat.Component; +#endif import org.jetbrains.annotations.Nullable; import java.util.AbstractMap; @@ -23,11 +30,25 @@ public class ConfigGuiInfo implements IConfigGuiInfo * Used to display validation errors. * Null if no error is present. */ + @Nullable + #if MC_VER <= MC_1_12_2 + public ITextComponent errorMessage; + #else public Component errorMessage; + #endif + + #if MC_VER <= MC_1_12_2 + public BiFunction> tooltipFunction; + #else + public BiFunction> tooltipFunction; + #endif - public BiFunction> tooltipFunction; /** determines which options the button will show */ + #if MC_VER <= MC_1_12_2 + public AbstractMap.SimpleEntry> buttonOptionMap; + #else public AbstractMap.SimpleEntry> buttonOptionMap; + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java index c578c0451..9f931db62 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java @@ -1,5 +1,5 @@ package com.seibel.distanthorizons.common.wrappers.gui.updater; - +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.gui.DhScreen; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -296,4 +296,5 @@ public class ChangelogScreen extends DhScreen } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java index 077567c83..d254c0601 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/UpdateModScreen.java @@ -1,5 +1,5 @@ package com.seibel.distanthorizons.common.wrappers.gui.updater; - +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch; import com.seibel.distanthorizons.common.wrappers.gui.DhScreen; import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; @@ -221,4 +221,5 @@ public class UpdateModScreen extends DhScreen Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Go to the parent screen } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/KeyedClientLevelManager.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/KeyedClientLevelManager.java index 22e6714ca..cea4e977b 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/KeyedClientLevelManager.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/KeyedClientLevelManager.java @@ -4,8 +4,11 @@ import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; -import net.minecraft.client.Minecraft; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.multiplayer.WorldClient; +#else import net.minecraft.client.multiplayer.ClientLevel; +#endif import org.jetbrains.annotations.Nullable; import java.util.Collections; @@ -41,14 +44,18 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager //=============// // constructor // //=============// + //region private KeyedClientLevelManager() { } + //endregion + //======================// // level override logic // //======================// + //region @Override @Nullable diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/ServerKeyedClientLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/ServerKeyedClientLevelWrapper.java index f6c661be3..147191346 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/ServerKeyedClientLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/ServerKeyedClientLevelWrapper.java @@ -2,7 +2,11 @@ package com.seibel.distanthorizons.common.wrappers.level; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.multiplayer.WorldClient; +#else import net.minecraft.client.multiplayer.ClientLevel; +#endif public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements IServerKeyedClientLevel { @@ -17,21 +21,30 @@ public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements //=============// // constructor // //=============// + //region + #if MC_VER <= MC_1_12_2 + public ServerKeyedClientLevelWrapper(WorldClient level, String serverKey, String serverLevelKey) + #else public ServerKeyedClientLevelWrapper(ClientLevel level, String serverKey, String serverLevelKey) + #endif { super(level); this.serverKey = serverKey; this.serverLevelKey = serverLevelKey; } + //endregion + - @Override - public String getServerKey() { return this.serverKey; } //======================// // level identification // //======================// + //region + + @Override + public String getServerKey() { return this.serverKey; } @Override public String getServerLevelKey() { return this.serverLevelKey; } @@ -39,6 +52,8 @@ public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements @Override public String getDhIdentifier() { return this.getServerLevelKey(); } + //endregion + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java index bda78b34d..9c253af43 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java @@ -21,7 +21,9 @@ package com.seibel.distanthorizons.common.wrappers.minecraft; import java.io.File; +#if MC_VER > MC_1_12_2 import com.mojang.blaze3d.platform.Window; +#endif import com.seibel.distanthorizons.common.wrappers.gui.NativeDialogUtil; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; @@ -40,22 +42,32 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.logging.DhLogger; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ServerData; +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.crash.CrashReport; +import net.minecraft.profiler.Profiler; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.text.TextComponentString; +#else import net.minecraft.CrashReport; import net.minecraft.client.CloudStatus; -import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.ChunkPos; +#endif import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -#if MC_VER < MC_1_19_2 +#if MC_VER < MC_1_19_2 && MC_VER > MC_1_12_2 import net.minecraft.network.chat.TextComponent; #endif @@ -64,7 +76,7 @@ import net.minecraft.network.chat.TextComponent; import net.minecraft.util.profiling.Profiler; #endif -#if MC_VER <= MC_1_21_10 +#if MC_VER <= MC_1_21_10 && MC_VER > MC_1_12_2 import net.minecraft.client.GraphicsStatus; #else #endif @@ -81,6 +93,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.core.Registry; #endif + /** * A singleton that wraps the Minecraft object. * @@ -89,7 +102,12 @@ import net.minecraft.core.Registry; public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper { private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + + #if MC_VER <= MC_1_12_2 + private static final Minecraft MINECRAFT = Minecraft.getMinecraft(); + #else private static final Minecraft MINECRAFT = Minecraft.getInstance(); + #endif public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper(); @@ -109,19 +127,36 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra //region @Override - public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); } - @Override - public boolean clientConnectedToDedicatedServer() - { - return MINECRAFT.getCurrentServer() != null - && !this.hasSinglePlayerServer(); + public boolean hasSinglePlayerServer() + { + #if MC_VER <= MC_1_12_2 + return MINECRAFT.isSingleplayer(); + #else + return MINECRAFT.hasSingleplayerServer(); + #endif } @Override - public boolean connectedToReplay() - { - return MINECRAFT.getCurrentServer() == null - && !this.hasSinglePlayerServer() ; + public boolean clientConnectedToDedicatedServer() + { + return this.hasServerConnection() + && !this.hasSinglePlayerServer(); } + @Override + public boolean connectedToReplay() + { + return !this.hasServerConnection() + && !this.hasSinglePlayerServer() ; + } + + private boolean hasServerConnection() + { + #if MC_VER <= MC_1_12_2 + return MINECRAFT.getCurrentServerData() != null; + #else + return MINECRAFT.getCurrentServer() != null; + #endif + } + @Override public String getCurrentServerName() @@ -132,8 +167,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra } else { + #if MC_VER <= MC_1_12_2 + ServerData server = MINECRAFT.getCurrentServerData(); + return (server != null) ? server.serverName : "NULL"; + #else ServerData server = MINECRAFT.getCurrentServer(); return (server != null) ? server.name : "NULL"; + #endif } } @Override @@ -145,17 +185,46 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra } else { - ServerData server = MINECRAFT.getCurrentServer(); - return (server != null) ? server.ip : "NA"; + ServerData server = getCurrentServerData(); + return getServerIp(server); } } @Override public String getCurrentServerVersion() { - ServerData server = MINECRAFT.getCurrentServer(); - return (server != null) ? server.version.getString() : "UNKOWN"; + ServerData server = getCurrentServerData(); + return getServerVersion(server); } + private ServerData getCurrentServerData() + { + #if MC_VER <= MC_1_12_2 + return MINECRAFT.getCurrentServerData(); + #else + return MINECRAFT.getCurrentServer(); + #endif + } + private String getServerIp(ServerData server) + { + if (server == null) { return "NA"; } + + #if MC_VER <= MC_1_12_2 + return server.serverIP; + #else + return server.ip; + #endif + } + private String getServerVersion(ServerData server) + { + if (server == null) { return "UNKOWN"; } + + #if MC_VER <= MC_1_12_2 + return server.gameVersion; + #else + return server.version.getString(); + #endif + } + //endregion @@ -165,7 +234,11 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra //=================// //region + #if MC_VER <= MC_1_12_2 + public EntityPlayerSP getPlayer() { return MINECRAFT.player; } + #else public LocalPlayer getPlayer() { return MINECRAFT.player; } + #endif @Override public boolean playerExists() { return MINECRAFT.player != null; } @@ -173,7 +246,11 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra @Override public DhBlockPos getPlayerBlockPos() { + #if MC_VER <= MC_1_12_2 + EntityPlayerSP player = this.getPlayer(); + #else LocalPlayer player = this.getPlayer(); + #endif if (player == null) { return new DhBlockPos(0, 0, 0); @@ -185,14 +262,22 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra if (pos != null) return pos; } + #if MC_VER <= MC_1_12_2 + BlockPos playerPos = player.getPosition(); + #else BlockPos playerPos = player.blockPosition(); + #endif return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ()); } @Override public DhChunkPos getPlayerChunkPos() { + #if MC_VER <= MC_1_12_2 + EntityPlayerSP player = this.getPlayer(); + #else LocalPlayer player = this.getPlayer(); + #endif if (player == null) { return new DhChunkPos(0, 0); @@ -204,7 +289,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra if (pos != null) return pos; } - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + ChunkPos playerPos = new ChunkPos(player.getPosition()); + #elif MC_VER < MC_1_17_1 ChunkPos playerPos = new ChunkPos(player.blockPosition()); #else ChunkPos playerPos = player.chunkPosition(); @@ -239,7 +326,11 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra IClientLevelWrapper level = Late.IMMERSIVE_PORTALS.getOriginalClientLevelWrapper(); if (level != null) return level; } + #if MC_VER <= MC_1_12_2 + WorldClient level = MINECRAFT.world; + #else ClientLevel level = MINECRAFT.level; + #endif if (level == null) { return null; @@ -260,13 +351,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra @Override public void sendChatMessage(String string) { + #if MC_VER <= MC_1_12_2 + EntityPlayerSP player = this.getPlayer(); + #else LocalPlayer player = this.getPlayer(); + #endif if (player == null) { return; } - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + player.sendMessage(new TextComponentString(string)); + #elif MC_VER < MC_1_19_2 player.sendMessage(new TextComponent(string), getPlayer().getUUID()); #elif MC_VER < MC_1_21_9 player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false); @@ -286,13 +383,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra @Override public void sendOverlayMessage(String string) { + #if MC_VER <= MC_1_12_2 + EntityPlayerSP player = this.getPlayer(); + #else LocalPlayer player = this.getPlayer(); + #endif if (player == null) { return; } - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + MINECRAFT.ingameGUI.setOverlayMessage(string, /*animateColor*/false); + #elif MC_VER < MC_1_19_2 player.displayClientMessage(new TextComponent(string), /*isOverlay*/true); #elif MC_VER <= MC_1_21_11 player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/true); @@ -314,7 +417,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra { LOGGER.info("Disabling vanilla clouds... This is done to prevent vanilla clouds from rendering on top of Distant Horizons LODs."); - #if MC_VER <= MC_1_18_2 + #if MC_VER <= MC_1_12_2 + MINECRAFT.gameSettings.clouds = 0; + #elif MC_VER <= MC_1_18_2 MINECRAFT.options.renderClouds = CloudStatus.OFF; #else MINECRAFT.options.cloudStatus().set(CloudStatus.OFF); @@ -323,11 +428,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra public void disableVanillaChunkFadeIn() { - LOGGER.info("Disabling vanilla chunk fade in... This is done to prevent vanilla chunks from flashing on the Distant Horizons boarder when moving (which is distracting)."); + String message = "Disabling vanilla chunk fade in... This is done to prevent vanilla chunks from flashing on the Distant Horizons boarder when moving (which is distracting)."; #if MC_VER <= MC_1_21_10 // chunk fade in was added MC 1.21.11 #else + LOGGER.info(message); + MINECRAFT.options.chunkSectionFadeInTime().set(0.0); #endif } @@ -336,7 +443,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra { String reasoning = "This is done to fix vanilla chunks (specifically water blocks) not fading into Distant Horizons LODs when DH's 'Vanilla Fade' option is enabled."; - #if MC_VER <= MC_1_18_2 + #if MC_VER <= MC_1_12_2 + // fabulous graphics was added in MC 1.16 + #elif MC_VER <= MC_1_18_2 LOGGER.info("Disabling fabulous graphics... "+reasoning); GraphicsStatus oldGraphicsStatus = MINECRAFT.options.graphicsMode; @@ -372,6 +481,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra * no override and not included in {@link IMinecraftClientWrapper} * since this would only be used in common/client, not core. */ + #if MC_VER > MC_1_12_2 public #if MC_VER < MC_1_21_9 long #else Window @@ -385,12 +495,20 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra return MINECRAFT.getWindow(); #endif } + #endif @Override public IProfilerWrapper getProfiler() { + #if MC_VER <= MC_1_12_2 + Profiler profiler; + #else ProfilerFiller profiler; - #if MC_VER < MC_1_21_3 + #endif + + #if MC_VER <= MC_1_12_2 + profiler = MINECRAFT.profiler; + #elif MC_VER < MC_1_21_3 profiler = MINECRAFT.getProfiler(); #else profiler = Profiler.get(); @@ -419,7 +537,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra executeOnRenderThread(() -> { CrashReport report = new CrashReport(errorMessage, exception); - #if MC_VER < MC_1_20_4 + #if MC_VER <= MC_1_12_2 + MINECRAFT.crashed(report); + #elif MC_VER < MC_1_20_4 Minecraft.crash(report); #else MINECRAFT.delayCrash(report); @@ -428,7 +548,14 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra } @Override - public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); } + public void executeOnRenderThread(Runnable runnable) + { + #if MC_VER <= MC_1_12_2 + MINECRAFT.addScheduledTask(runnable); + #else + MINECRAFT.execute(runnable); + #endif + } @Override public void showDialog(String title, String message, String dialogType, String iconType) @@ -444,7 +571,14 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra //region @Override - public Object getOptionsObject() { return MINECRAFT.options; } + public Object getOptionsObject() + { + #if MC_VER <= MC_1_12_2 + return MINECRAFT.gameSettings; + #else + return MINECRAFT.options; + #endif + } //endregion @@ -459,19 +593,34 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra public boolean isDedicatedServer() { return false; } @Override - public File getInstallationDirectory() { return MINECRAFT.gameDirectory; } + public File getInstallationDirectory() + { + #if MC_VER <= MC_1_12_2 + return MINECRAFT.gameDir; + #else + return MINECRAFT.gameDirectory; + #endif + } @Override public int getPlayerCount() { // can be null if the server hasn't finished booting up yet + #if MC_VER <= MC_1_12_2 + if (MINECRAFT.getIntegratedServer() == null) + #else if (MINECRAFT.getSingleplayerServer() == null) + #endif { return 1; } else { + #if MC_VER <= MC_1_12_2 + return MINECRAFT.getIntegratedServer().getCurrentPlayerCount(); + #else return MINECRAFT.getSingleplayerServer().getPlayerCount(); + #endif } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftGLWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftGLWrapper.java index 56baa6953..4639d2ae2 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftGLWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftGLWrapper.java @@ -19,7 +19,9 @@ package com.seibel.distanthorizons.common.wrappers.minecraft; -#if MC_VER < MC_1_21_5 +#if MC_VER <= MC_1_12_2 +import net.minecraft.client.renderer.GlStateManager; +#elif MC_VER < MC_1_21_5 import com.mojang.blaze3d.platform.GlStateManager; #else import com.mojang.blaze3d.opengl.GlStateManager; @@ -36,7 +38,7 @@ import org.lwjgl.opengl.GL32; * Why does DH often call GL methods twice?
* Once using the base {@link GL32} function and a second time using * Minecraft's {@link GlStateManager}?

- * + * * Answer:
* Compatibility and robustness
* In general all MC rendering should go through MC's {@link GlStateManager}, @@ -66,16 +68,20 @@ public class MinecraftGLWrapper // scissor // /** @see GL32#GL_SCISSOR_TEST */ - public void enableScissorTest() + public void enableScissorTest() { GL32.glEnable(GL32.GL_SCISSOR_TEST); + #if MC_VER > MC_1_12_2 GlStateManager._enableScissorTest(); + #endif } /** @see GL32#GL_SCISSOR_TEST */ - public void disableScissorTest() - { + public void disableScissorTest() + { GL32.glDisable(GL32.GL_SCISSOR_TEST); - GlStateManager._disableScissorTest(); + #if MC_VER > MC_1_12_2 + GlStateManager._disableScissorTest(); + #endif } @@ -90,78 +96,113 @@ public class MinecraftGLWrapper // depth // /** @see GL32#GL_DEPTH_TEST */ - public void enableDepthTest() + public void enableDepthTest() { GL32.glEnable(GL32.GL_DEPTH_TEST); + #if MC_VER <= MC_1_12_2 + GlStateManager.enableDepth(); + #else GlStateManager._enableDepthTest(); + #endif } /** @see GL32#GL_DEPTH_TEST */ - public void disableDepthTest() + public void disableDepthTest() { GL32.glDisable(GL32.GL_DEPTH_TEST); + #if MC_VER <= MC_1_12_2 + GlStateManager.disableDepth(); + #else GlStateManager._disableDepthTest(); + #endif } /** @see GL32#glDepthFunc(int) */ - public void glDepthFunc(int func) - { + public void glDepthFunc(int func) + { GL32.glDepthFunc(func); + #if MC_VER <= MC_1_12_2 + GlStateManager.depthFunc(func); + #else GlStateManager._depthFunc(func); + #endif } /** @see GL32#glDepthMask(boolean) */ - public void enableDepthMask() + public void enableDepthMask() { GL32.glDepthMask(true); - GlStateManager._depthMask(true); + #if MC_VER <= MC_1_12_2 + GlStateManager.depthMask(true); + #else + GlStateManager._depthMask(true); + #endif } /** @see GL32#glDepthMask(boolean) */ - public void disableDepthMask() + public void disableDepthMask() { GL32.glDepthMask(false); + #if MC_VER <= MC_1_12_2 + GlStateManager.depthMask(false); + #else GlStateManager._depthMask(false); + #endif } // blending // /** @see GL32#GL_BLEND */ - public void enableBlend() + public void enableBlend() { GL32.glEnable(GL32.GL_BLEND); + #if MC_VER <= MC_1_12_2 + GlStateManager.enableBlend(); + #else GlStateManager._enableBlend(); + #endif } /** @see GL32#GL_BLEND */ - public void disableBlend() + public void disableBlend() { GL32.glDisable(GL32.GL_BLEND); + #if MC_VER <= MC_1_12_2 + GlStateManager.disableBlend(); + #else GlStateManager._disableBlend(); + #endif } /** @see GL32#glBlendFunc */ - public void glBlendFunc(int sfactor, int dfactor) + public void glBlendFunc(int sfactor, int dfactor) { GL32.glBlendFunc(sfactor, dfactor); - - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + GlStateManager.blendFunc(sfactor, dfactor); + #elif MC_VER < MC_1_21_5 GlStateManager._blendFunc(sfactor, dfactor); #endif } /** @see GL32#glBlendFuncSeparate */ - public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha) + public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha) { GL32.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); - GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); + #if MC_VER <= MC_1_12_2 + GlStateManager.tryBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); + #else + GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); + #endif } // frame buffers // /** @see GL32#glBindFramebuffer */ - public void glBindFramebuffer(int target, int framebuffer) + public void glBindFramebuffer(int target, int framebuffer) { GL32.glBindFramebuffer(target, framebuffer); - GlStateManager._glBindFramebuffer(target, framebuffer); + #if MC_VER > MC_1_12_2 + GlStateManager._glBindFramebuffer(target, framebuffer); + #endif } @@ -187,31 +228,57 @@ public class MinecraftGLWrapper // culling // /** @see GL32#GL_CULL_FACE */ - public void enableFaceCulling() + public void enableFaceCulling() { GL32.glEnable(GL32.GL_CULL_FACE); - GlStateManager._enableCull(); + #if MC_VER <= MC_1_12_2 + GlStateManager.enableCull(); + #else + GlStateManager._enableCull(); + #endif } /** @see GL32#GL_CULL_FACE */ - public void disableFaceCulling() + public void disableFaceCulling() { GL32.glDisable(GL32.GL_CULL_FACE); - GlStateManager._disableCull(); + #if MC_VER <= MC_1_12_2 + GlStateManager.disableCull(); + #else + GlStateManager._disableCull(); + #endif } // textures // /** @see GL32#glGenTextures() */ - public int glGenTextures() { return GlStateManager._genTexture(); } + public int glGenTextures() + { + #if MC_VER <= MC_1_12_2 + return GlStateManager.generateTexture(); + #else + return GlStateManager._genTexture(); + #endif + } /** @see GL32#glDeleteTextures(int) */ - public void glDeleteTextures(int texture) { GlStateManager._deleteTexture(texture); } + public void glDeleteTextures(int texture) + { + #if MC_VER <= MC_1_12_2 + GlStateManager.deleteTexture(texture); + #else + GlStateManager._deleteTexture(texture); + #endif + } /** @see GL32#glActiveTexture(int) */ - public void glActiveTexture(int textureId) - { + public void glActiveTexture(int textureId) + { GL32.glActiveTexture(textureId); + #if MC_VER <= MC_1_12_2 + GlStateManager.setActiveTexture(textureId); + #else GlStateManager._activeTexture(textureId); + #endif } public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); } @@ -219,10 +286,14 @@ public class MinecraftGLWrapper * Always binds to {@link GL32#GL_TEXTURE_2D} * @see GL32#glBindTexture(int, int) */ - public void glBindTexture(int texture) + public void glBindTexture(int texture) { GL32.glBindTexture(GL32.GL_TEXTURE_2D, texture); + #if MC_VER <= MC_1_12_2 + GlStateManager.bindTexture(texture); + #else GlStateManager._bindTexture(texture); + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java index a98e8a527..974e424e0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java @@ -22,8 +22,10 @@ package com.seibel.distanthorizons.common.wrappers.minecraft; import java.awt.Color; import java.util.concurrent.ConcurrentHashMap; +#if MC_VER > MC_1_12_2 import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.NativeImage; +#endif import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading; import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper; @@ -64,19 +66,29 @@ import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor; +#if MC_VER <= MC_1_12_2 +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.IFluidBlock; +import net.minecraft.init.MobEffects; +import net.minecraft.client.renderer.entity.RenderManager; +#else import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.phys.Vec3; +#endif +import net.minecraft.client.Minecraft; import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Vector4f; -#if MC_VER < MC_1_17_1 +#if MC_VER <= MC_1_12_2 +import org.lwjgl.opengl.GL15; +#elif MC_VER < MC_1_17_1 import net.minecraft.tags.FluidTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.material.FluidState; @@ -108,7 +120,12 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + + #if MC_VER <= MC_1_12_2 + private static final Minecraft MC = Minecraft.getMinecraft(); + #else private static final Minecraft MC = Minecraft.getInstance(); + #endif /** * In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps.
@@ -139,7 +156,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public Vec3f getLookAtVector() { - #if MC_VER <= MC_1_21_10 + #if MC_VER <= MC_1_12_2 + net.minecraft.util.math.Vec3d lookVector = (MC.getRenderViewEntity().getLook(MC.getRenderPartialTicks())); + return new Vec3f((float) lookVector.x, (float) lookVector.y, (float) lookVector.z); + #elif MC_VER <= MC_1_21_10 Camera camera = MC.gameRenderer.getMainCamera(); return new Vec3f(camera.getLookVector().x(), camera.getLookVector().y(), camera.getLookVector().z()); #else @@ -159,37 +179,52 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper { return false; } - else if (MC.player.getActiveEffectsMap() == null) + + #if MC_VER <= MC_1_12_2 + if (MC.player.getActivePotionMap() == null) { return false; } - else + + return MC.player.getActivePotionEffect(MobEffects.BLINDNESS) != null; + #else + if (MC.player.getActiveEffectsMap() == null) { - return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null - #if MC_VER >= MC_1_19_2 - || MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect - #endif - ; + return false; } + + return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null + #if MC_VER >= MC_1_19_2 + || MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect + #endif + ; + #endif + } @Override public Vec3d getCameraExactPosition() { + #if MC_VER <= MC_1_12_2 + RenderManager rm = MC.getRenderManager(); + return new Vec3d(rm.viewerPosX, rm.viewerPosY, rm.viewerPosZ); + #else Camera camera = MC.gameRenderer.getMainCamera(); #if MC_VER <= MC_1_21_10 Vec3 projectedView = camera.getPosition(); #else Vec3 projectedView = camera.position(); #endif - return new Vec3d(projectedView.x, projectedView.y, projectedView.z); + #endif } @Override public float getPartialTickTime() { - #if MC_VER < MC_1_21_1 + #if MC_VER <= MC_1_12_2 + return MC.getRenderPartialTicks(); + #elif MC_VER < MC_1_21_1 return MC.getFrameTime(); #elif MC_VER < MC_1_21_3 return MC.getTimer().getRealtimeDeltaTicks(); @@ -302,9 +337,17 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public Color getSkyColor() { + #if MC_VER <= MC_1_12_2 + if (MC.world.provider.hasSkyLight()) + #else if (MC.level.dimensionType().hasSkyLight()) + #endif { - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + float frameTime = this.getPartialTickTime(); + net.minecraft.util.math.Vec3d colorValues = MC.world.getSkyColor(MC.getRenderViewEntity(), frameTime); + return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z); + #elif MC_VER < MC_1_17_1 float frameTime = this.getPartialTickTime(); Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime); return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z); @@ -331,7 +374,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public int getRenderDistance() { - #if MC_VER <= MC_1_17_1 + #if MC_VER <= MC_1_12_2 + return MC.gameSettings.renderDistanceChunks; + #elif MC_VER <= MC_1_17_1 return MC.options.renderDistance; #else return MC.options.getEffectiveRenderDistance(); @@ -341,14 +386,18 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public int getFrameLimit() { - #if MC_VER <= MC_1_18_2 + #if MC_VER <= MC_1_12_2 + return MC.gameSettings.limitFramerate; + #elif MC_VER <= MC_1_18_2 return MC.options.framerateLimit; #else return MC.options.framerateLimit().get(); #endif } + #if MC_VER > MC_1_12_2 protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); } + #endif @Override public boolean mcRendersToFrameBuffer() @@ -379,7 +428,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper return this.finalLevelFrameBufferId; } - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + return MC.getFramebuffer().framebufferObject; + #elif MC_VER < MC_1_21_5 return this.getRenderTarget().frameBufferId; #else // MC renders to a texture and then directly to the default FBO now @@ -394,7 +445,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public int getDepthTextureId() { - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + //1.12.2 is using renderbuffer instead of framebuffer for depth texture + return -1; + #elif MC_VER < MC_1_21_5 return this.getRenderTarget().getDepthTextureId(); #else try @@ -424,7 +478,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public int getColorTextureId() { - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + return MC.getFramebuffer().framebufferTexture; + #elif MC_VER < MC_1_21_5 return this.getRenderTarget().getColorTextureId(); #else try @@ -454,7 +510,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public int getTargetFramebufferViewportWidth() { - #if MC_VER < MC_1_21_9 + #if MC_VER <= MC_1_12_2 + return MC.getFramebuffer().framebufferWidth; + #elif MC_VER < MC_1_21_9 return this.getRenderTarget().viewWidth; #else return this.getRenderTarget().width; @@ -464,7 +522,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public int getTargetFramebufferViewportHeight() { - #if MC_VER < MC_1_21_9 + #if MC_VER <= MC_1_12_2 + return MC.getFramebuffer().framebufferHeight; + #elif MC_VER < MC_1_21_9 return this.getRenderTarget().viewHeight; #else return this.getRenderTarget().height; @@ -474,7 +534,11 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper @Override public boolean isFogStateSpecial() { - #if MC_VER < MC_1_17_1 + #if MC_VER <= MC_1_12_2 + BlockPos blockPos = new BlockPos(MC.getRenderViewEntity().getPositionEyes(MC.getRenderPartialTicks())); + IBlockState fluidState = MC.getRenderViewEntity().world.getBlockState(blockPos); + return this.playerHasBlindingEffect() || fluidState.getMaterial().isLiquid() || fluidState.getBlock() instanceof IFluidBlock; + #elif MC_VER < MC_1_17_1 Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera(); FluidState fluidState = camera.getFluidInCamera(); Entity entity = camera.getEntity(); @@ -502,6 +566,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper * It's better to use {@link MinecraftRenderWrapper#setLightmapId(int)} if possible, * however old MC versions don't support it. */ + #if MC_VER > MC_1_12_2 public void updateLightmap(NativeImage lightPixels) { IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper(); @@ -518,6 +583,8 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper()); wrapper.uploadLightmap(lightPixels); } + #endif + public void setLightmapId(int textureId) { IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper(); @@ -578,6 +645,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper { default: case AUTO: + #if MC_VER <= MC_1_12_2 + // 1.12.2 has no getShade, fall through to ENABLED + #else if (MC.level != null) { Direction mcDir = McObjectConverter.Convert(lodDirection); @@ -591,7 +661,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper { return 0.0f; } - + #endif case ENABLED: switch (lodDirection) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftServerWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftServerWrapper.java index 4f967be79..fbb1539a9 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftServerWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftServerWrapper.java @@ -56,7 +56,9 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper throw new IllegalStateException("Trying to get Installation Direction before dedicated server completed initialization!"); } - #if MC_VER < MC_1_21_1 + #if MC_VER <= MC_1_12_2 + return this.dedicatedServer.getDataDirectory(); + #elif MC_VER < MC_1_21_1 return this.dedicatedServer.getServerDirectory(); #else return this.dedicatedServer.getServerDirectory().toFile(); @@ -71,7 +73,11 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper throw new IllegalStateException("Trying to get player count before dedicated server completed initialization!"); } - return this.dedicatedServer.getPlayerCount(); + #if MC_VER <= MC_1_12_2 + return this.dedicatedServer.getCurrentPlayerCount(); + #else + return this.dedicatedServer.getPlayerCount(); + #endif } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/ProfilerWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/ProfilerWrapper.java index b9e4392fc..89c4e4b4b 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/ProfilerWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/ProfilerWrapper.java @@ -21,25 +21,50 @@ package com.seibel.distanthorizons.common.wrappers.minecraft; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.profiler.Profiler; +#else import net.minecraft.util.profiling.ProfilerFiller; +#endif public class ProfilerWrapper implements IProfilerWrapper { + #if MC_VER <= MC_1_12_2 + public Profiler profiler; + #else public ProfilerFiller profiler; + #endif + + + + #if MC_VER <= MC_1_12_2 + public ProfilerWrapper(Profiler newProfiler) + #else + public ProfilerWrapper(ProfilerFiller newProfiler) + #endif + { this.profiler = newProfiler; } + - public ProfilerWrapper(ProfilerFiller newProfiler) { this.profiler = newProfiler; } @Override public IProfileBlock push(String newSection) { - this.profiler.push(newSection); + #if MC_VER <= MC_1_12_2 + this.profiler.startSection(newSection); + #else + this.profiler.push(newSection); + #endif return new ProfileBlock(this.profiler); } @Override public void popPush(String newSection) { - this.profiler.popPush(newSection); + #if MC_VER <= MC_1_12_2 + this.profiler.endStartSection(newSection); + #else + this.profiler.popPush(newSection) ; + #endif } @@ -51,14 +76,27 @@ public class ProfilerWrapper implements IProfilerWrapper public static class ProfileBlock implements IProfileBlock { - private final ProfilerFiller profiler; - public ProfileBlock(ProfilerFiller newProfiler) { this.profiler = newProfiler; } - + #if MC_VER <= MC_1_12_2 + public Profiler profiler; + #else + public ProfilerFiller profiler; + #endif + + #if MC_VER <= MC_1_12_2 + public ProfileBlock(Profiler newProfiler) + #else + public ProfileBlock(ProfilerFiller newProfiler) + #endif + { this.profiler = newProfiler; } @Override public void close() { + #if MC_VER <= MC_1_12_2 + this.profiler.endSection(); + #else this.profiler.pop(); + #endif } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/IMixinServerPlayer.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/IMixinServerPlayer.java index 2e2783843..fc80b31e8 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/IMixinServerPlayer.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/IMixinServerPlayer.java @@ -1,12 +1,21 @@ package com.seibel.distanthorizons.common.wrappers.misc; +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.WorldServer; +#else import net.minecraft.server.level.ServerLevel; +#endif + import org.jetbrains.annotations.Nullable; public interface IMixinServerPlayer { @Nullable + #if MC_VER <= MC_1_12_2 + WorldServer distantHorizons$getDimensionChangeDestination(); + #else ServerLevel distantHorizons$getDimensionChangeDestination(); + #endif #if MC_VER == MC_1_16_5 void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java index 775a5ef77..22e6edd57 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java @@ -19,9 +19,13 @@ package com.seibel.distanthorizons.common.wrappers.misc; +#if MC_VER > MC_1_12_2 import com.mojang.blaze3d.platform.NativeImage; import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper; +#endif +import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; import com.seibel.distanthorizons.core.logging.DhLogger; @@ -58,7 +62,6 @@ public class LightMapWrapper implements ILightMapWrapper private final BlazeTextureViewWrapper lightmapTextureWrapper = new BlazeTextureViewWrapper(); - //==============// // constructors // //==============// @@ -75,6 +78,7 @@ public class LightMapWrapper implements ILightMapWrapper //==================// //region + #if MC_VER > MC_1_12_2 public void uploadLightmap(NativeImage image) { #if MC_VER < MC_1_21_3 @@ -110,6 +114,7 @@ public class LightMapWrapper implements ILightMapWrapper throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.3"); #endif } + #endif public void setLightmapId(int minecraftLightmapTextureId) { @@ -126,6 +131,7 @@ public class LightMapWrapper implements ILightMapWrapper } #endif + //endregion diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/MutableBlockPosWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/MutableBlockPosWrapper.java index d8de52924..a1b3f93b9 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/MutableBlockPosWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/MutableBlockPosWrapper.java @@ -1,7 +1,11 @@ package com.seibel.distanthorizons.common.wrappers.misc; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.math.BlockPos; +#else import net.minecraft.core.BlockPos; +#endif public class MutableBlockPosWrapper implements IMutableBlockPosWrapper { @@ -12,19 +16,27 @@ public class MutableBlockPosWrapper implements IMutableBlockPosWrapper //=============// // constructor // //=============// + //region public MutableBlockPosWrapper() { this.pos = new BlockPos.MutableBlockPos(); } + //endregion + //===========// // overrides // //===========// + //region @Override public Object getWrappedMcObject() { return this.pos; } + //endregion + + + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java index 8677000ad..91b052577 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java @@ -6,53 +6,114 @@ import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.util.math.Vec3d; +#if MC_VER <= MC_1_12_2 +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldServer; +#else import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.phys.Vec3; +#endif import java.net.SocketAddress; import java.util.concurrent.ConcurrentMap; +#if MC_VER <= MC_1_12_2 + +/** + * This wrapper transparently ensures that the underlying {@link EntityPlayerMP} is always valid, + * unless the player has disconnected. + */ +#else /** * This wrapper transparently ensures that the underlying {@link ServerPlayer} is always valid, * unless the player has disconnected. */ +#endif public class ServerPlayerWrapper implements IServerPlayerWrapper { + #if MC_VER <= MC_1_12_2 + private static final ConcurrentMap serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap(); + #else private static final ConcurrentMap serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap(); + #endif + #if MC_VER <= MC_1_12_2 + private final NetHandlerPlayServer connection; + #else private final ServerGamePacketListenerImpl connection; + #endif //=============// // constructor // //=============// + //region - public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer) + #if MC_VER <= MC_1_12_2 + public static ServerPlayerWrapper getWrapper(EntityPlayerMP serverPlayer) + #else + public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer) + #endif { return serverPlayerWrapperMap.computeIfAbsent(serverPlayer.connection, ignored -> new ServerPlayerWrapper(serverPlayer.connection)); } - private ServerPlayerWrapper(ServerGamePacketListenerImpl connection) { this.connection = connection; } + #if MC_VER <= MC_1_12_2 + private ServerPlayerWrapper(NetHandlerPlayServer connection) + #else + private ServerPlayerWrapper(ServerGamePacketListenerImpl connection) + #endif + { this.connection = connection; } + + //endregion //=========// // getters // //=========// + //region - private ServerPlayer getServerPlayer() { return this.connection.player; } + #if MC_VER <= MC_1_12_2 + private EntityPlayerMP getServerPlayer() + #else + private ServerPlayer getServerPlayer() + #endif + { return this.connection.player; } @Override - public String getName() { return this.getServerPlayer().getName().getString(); } + public String getName() + { + #if MC_VER <= MC_1_12_2 + return this.getServerPlayer().getName(); + #else + return this.getServerPlayer().getName().getString(); + #endif + } @Override public IServerLevelWrapper getLevel() { - ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination(); + #if MC_VER <= MC_1_12_2 + WorldServer level = null; + if (this.getServerPlayer() instanceof IMixinServerPlayer mixinPlayer) + { + level = mixinPlayer.distantHorizons$getDimensionChangeDestination(); + } + #else + ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination(); + #endif + if (level == null) { - #if MC_VER < MC_1_20_1 + #if MC_VER <= MC_1_12_2 + MinecraftServer server = this.getServerPlayer().getServer(); + level = (server != null) ? server.getWorld(this.getServerPlayer().dimension) : this.getServerPlayer().getServerWorld(); + #elif MC_VER < MC_1_20_1 level = this.getServerPlayer().getLevel(); #elif MC_VER < MC_1_21_6 level = this.getServerPlayer().serverLevel(); @@ -67,15 +128,23 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper @Override public Vec3d getPosition() { + #if MC_VER <= MC_1_12_2 + BlockPos position = this.getServerPlayer().getPosition(); + return new Vec3d(position.getX(), position.getY(), position.getZ()); + #else Vec3 position = this.getServerPlayer().position(); return new Vec3d(position.x, position.y, position.z); + #endif } + //endregion + //================// // base overrides // //================// + //region @Override public Object getWrappedMcObject() { return this.getServerPlayer(); } @@ -101,4 +170,8 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper @Override public int hashCode() { return Objects.hashCode(this.connection); } + //endregion + + + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java index a1c219c86..368fbd20e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java @@ -5,7 +5,9 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegist import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper; import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper; import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache; +import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager; +import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -20,12 +22,22 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; + import net.minecraft.client.Minecraft; +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.WorldServer; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.block.state.IBlockState; +#else import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +#endif import com.seibel.distanthorizons.core.logging.DhLogger; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,8 +50,15 @@ import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; +#if MC_VER <= MC_1_12_2 +#elif MC_VER <= MC_1_20_4 +import net.minecraft.world.level.chunk.ChunkStatus; +#else +import net.minecraft.world.level.chunk.status.ChunkStatus; +#endif -#if MC_VER < MC_1_21_3 +#if MC_VER <= MC_1_12_2 +#elif MC_VER < MC_1_21_3 import net.minecraft.world.phys.Vec3; #else import com.seibel.distanthorizons.coreapi.util.ColorUtil; @@ -59,20 +78,35 @@ public class ClientLevelWrapper implements IClientLevelWrapper * where, upon world closure, some levels aren't shutdown/removed properly * and/or for servers were the level object isn't consistent */ - private static final Map> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>()); + private static final Map< + #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif, + WeakReference> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>()); private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class); + #if MC_VER <= MC_1_12_2 + private static final Minecraft MINECRAFT = Minecraft.getMinecraft(); + #else private static final Minecraft MINECRAFT = Minecraft.getInstance(); + #endif private static final Timer CLIENT_CLEANUP_TIMER = TimerUtil.CreateTimer("ClientLevelTickCleanup"); private static final TimerTask CLIENT_CLEANUP_TASK = TimerUtil.createTimerTask(ClientLevelWrapper::tickCleanup); + #if MC_VER <= MC_1_12_2 + private final WorldClient level; + private final ConcurrentHashMap blockColorCacheByBlockState = new ConcurrentHashMap<>(); + #else private final ClientLevel level; private final ConcurrentHashMap blockColorCacheByBlockState = new ConcurrentHashMap<>(); + #endif + /** cached method reference to reduce GC overhead */ - private final Function createCachedBlockColorCacheFunc = (blockState) -> new ClientBlockStateColorCache(blockState, this); + private final Function< + #if MC_VER <= MC_1_12_2 IBlockState #else BlockState #endif, + ClientBlockStateColorCache> createCachedBlockColorCacheFunc + = (blockState) -> new ClientBlockStateColorCache(blockState, this); private boolean cloudColorFailLogged = false; @@ -88,7 +122,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper //=============// //region - protected ClientLevelWrapper(ClientLevel level) { this.level = level; } + protected ClientLevelWrapper(#if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level) { this.level = level; } //endregion @@ -169,7 +203,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper * IE rendering. */ @Nullable - public static IClientLevelWrapper getWrapperIfDifferent(@Nullable IClientLevelWrapper levelWrapper, @NotNull ClientLevel level) + public static IClientLevelWrapper getWrapperIfDifferent( + @Nullable IClientLevelWrapper levelWrapper, + @NotNull #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level) { if (KEYED_CLIENT_LEVEL_MANAGER.isEnabled()) { @@ -202,10 +238,13 @@ public class ClientLevelWrapper implements IClientLevelWrapper } @Nullable - public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); } + public static IClientLevelWrapper getWrapper( + @NotNull #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level) + { return getWrapper(level, false); } @Nullable - public static IClientLevelWrapper getWrapper(@Nullable ClientLevel level, boolean bypassLevelKeyManager) + public static IClientLevelWrapper getWrapper( + @Nullable #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level, boolean bypassLevelKeyManager) { if (!bypassLevelKeyManager) { @@ -278,19 +317,27 @@ public class ClientLevelWrapper implements IClientLevelWrapper try { // this method only makes sense if we are running a single-player server - if (MINECRAFT.getSingleplayerServer() == null) + if (MINECRAFT.#if MC_VER <= MC_1_12_2 getIntegratedServer() #else getSingleplayerServer() #endif == null) { return null; } + #if MC_VER <= MC_1_12_2 + WorldServer[] serverLevels = MINECRAFT.getIntegratedServer().worlds; + #else Iterable serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels(); + #endif // attempt to find the server level with the same dimension type // Note: this assumes only one level per dimension type, multiverse servers may not behave correctly ServerLevelWrapper foundLevelWrapper = null; - for (ServerLevel serverLevel : serverLevels) + for (#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif serverLevel : serverLevels) { + #if MC_VER <= MC_1_12_2 + if (serverLevel.provider.getDimension() == this.level.provider.getDimension()) + #else if (serverLevel.dimension() == this.level.dimension()) + #endif { foundLevelWrapper = ServerLevelWrapper.getWrapper(serverLevel); break; @@ -363,7 +410,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper return this.dimensionTypeWrapper; } - #if MC_VER <= MC_1_21_10 + #if MC_VER <= MC_1_12_2 + this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.provider.getDimensionType()); + #elif MC_VER <= MC_1_21_10 this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); #else this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName()); @@ -382,8 +431,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper return this.dimensionName; } - - #if MC_VER <= MC_1_21_10 + #if MC_VER <= MC_1_12_2 + this.dimensionName = this.level.provider.getDimensionType().getName(); + #elif MC_VER <= MC_1_21_10 this.dimensionName = this.level.dimension().location().toString(); #else this.dimensionName = this.level.dimension().identifier().toString(); @@ -392,7 +442,14 @@ public class ClientLevelWrapper implements IClientLevelWrapper } @Override - public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; } + public long getHashedSeed() + { + #if MC_VER <= MC_1_12_2 + return this.level.getSeed(); + #else + return this.level.getBiomeManager().biomeZoomSeed; + #endif + } @Override public String getDhIdentifier() { return this.getHashedSeedEncoded() + "@" + this.getDimensionName(); } @@ -400,7 +457,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper @Override public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; } - public ClientLevel getLevel() { return this.level; } + public #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif getLevel() { return this.level; } private Boolean dimHasCeiling = null; @Override @@ -413,8 +470,12 @@ public class ClientLevelWrapper implements IClientLevelWrapper return this.dimHasCeiling; } - + #if MC_VER <= MC_1_12_2 + // 1.12.2 has no hasCeiling() - only the nether has a ceiling in vanilla + this.dimHasCeiling = this.level.provider.isNether(); + #else this.dimHasCeiling = this.level.dimensionType().hasCeiling(); + #endif return this.dimHasCeiling; } @@ -429,7 +490,11 @@ public class ClientLevelWrapper implements IClientLevelWrapper return this.dimHasSkyLight; } + #if MC_VER <= MC_1_12_2 + this.dimHasSkyLight = this.level.provider.hasSkyLight(); + #else this.dimHasSkyLight = this.level.dimensionType().hasSkyLight(); + #endif return this.dimHasSkyLight; } @@ -471,7 +536,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper } @Override - public ClientLevel getWrappedMcObject() { return this.level; } + public #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif getWrappedMcObject() { return this.level; } @Override public void onUnload() @@ -520,10 +585,20 @@ public class ClientLevelWrapper implements IClientLevelWrapper public Color getCloudColor(float tickDelta) { #if MC_VER < MC_1_21_3 + + #if MC_VER <= MC_1_12_2 + Vec3d colorVec3 = null; + #else Vec3 colorVec3 = null; + #endif try { + #if MC_VER <= MC_1_12_2 + colorVec3 = this.level.getCloudColour(tickDelta); + #else colorVec3 = this.level.getCloudColor(tickDelta); + #endif + return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z); } catch (Exception e) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/DimensionTypeWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/DimensionTypeWrapper.java index 8a77a092e..1f5ce1b8b 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/DimensionTypeWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/DimensionTypeWrapper.java @@ -24,7 +24,11 @@ import java.util.concurrent.ConcurrentMap; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.DimensionType; +#else import net.minecraft.world.level.dimension.DimensionType; +#endif public class DimensionTypeWrapper implements IDimensionTypeWrapper { @@ -86,7 +90,9 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper } private static String determineName(DimensionType dimensionType) { - #if MC_VER <= MC_1_16_5 + #if MC_VER <= MC_1_12_2 + return dimensionType.getName(); + #elif MC_VER <= MC_1_16_5 // effectsLocation() is marked as client only, so using the backing field directly return dimensionType.effectsLocation.getPath(); #elif MC_VER <= MC_1_21_10 @@ -108,10 +114,26 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper public String getName() { return this.name; } @Override - public boolean hasCeiling() { return this.dimensionType.hasCeiling(); } + public boolean hasCeiling() + { + #if MC_VER <= MC_1_12_2 + // 1.12.2 has no hasCeiling() - only the nether has a ceiling in vanilla + return this.dimensionType.getId() == -1; + #else + return this.dimensionType.hasCeiling(); + #endif + } @Override - public boolean hasSkyLight() { return this.dimensionType.hasSkyLight(); } + public boolean hasSkyLight() + { + #if MC_VER <= MC_1_12_2 + // 1.12.2 DimensionType doesn't store hasSkyLight, it's in the WorldProvider instead + return this.dimensionType != DimensionType.NETHER; + #else + return this.dimensionType.hasSkyLight(); + #endif + } @Override public Object getWrappedMcObject() { return this.dimensionType; } @@ -120,7 +142,15 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); } @Override - public double getCoordinateScale() { return this.dimensionType.coordinateScale(); } + public double getCoordinateScale() + { + #if MC_VER <= MC_1_12_2 + // 1.12.2 DimensionType doesn't store coordinate scale, it's in the WorldProvider instead + return this.dimensionType == net.minecraft.world.DimensionType.NETHER ? 8.0 : 1.0; + #else + return this.dimensionType.coordinateScale(); + #endif + } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java index e400dcf76..1a939a44a 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java @@ -38,12 +38,17 @@ import com.seibel.distanthorizons.core.world.EWorldEnvironment; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.WorldServer; +#else import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkSource; +#endif -#if MC_VER <= MC_1_20_4 +#if MC_VER <= MC_1_12_2 +#elif MC_VER <= MC_1_20_4 import net.minecraft.world.level.chunk.ChunkStatus; #else import net.minecraft.world.level.chunk.status.ChunkStatus; @@ -59,10 +64,10 @@ public class ServerLevelWrapper implements IServerLevelWrapper * weak references are to prevent rare issues * where, upon world closure, some levels aren't shutdown/removed properly */ - private static final Map> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>()); + private static final Map<#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif, WeakReference> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>()); - private final ServerLevel level; - private volatile IDhLevel dhLevel; + private final #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level; + private IDhLevel dhLevel; /** * this name is cached to prevent issues during shutdown where @@ -76,7 +81,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper // constructors // //==============// - public static ServerLevelWrapper getWrapper(ServerLevel level) + public static ServerLevelWrapper getWrapper(#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level) { return LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.compute(level, (newLevel, levelRef) -> { @@ -93,7 +98,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper }).get(); } - public ServerLevelWrapper(ServerLevel level) + public ServerLevelWrapper(#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level) { this.level = level; this.KeyedLevelDimensionName = this.createKeyedLevelDimensionName(); @@ -108,7 +113,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper @Override public File getMcSaveFolder() { - #if MC_VER < MC_1_21_3 + #if MC_VER <= MC_1_12_2 + return new File(this.level.getChunkSaveLocation(), "data"); + #elif MC_VER < MC_1_21_3 return this.level.getChunkSource().getDataStorage().dataFolder; #else return this.level.getChunkSource().getDataStorage().dataFolder.toFile(); @@ -157,7 +164,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper { // We use the overworld since it's the only dimension that is stored in the server root folder - #if MC_VER >= MC_1_21_3 + #if MC_VER <= MC_1_12_2 + return this.level.getMinecraftServer().getWorld(0).getSaveHandler().getWorldDirectory().getParentFile().getName(); + #elif MC_VER >= MC_1_21_3 return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParent().getFileName().toString(); #else // <= 1.21.3 return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParentFile().getName(); @@ -174,7 +183,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper @Override public DimensionTypeWrapper getDimensionType() { - #if MC_VER <= MC_1_21_10 + #if MC_VER <= MC_1_12_2 + return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.provider.getDimensionType()); + #elif MC_VER <= MC_1_21_10 return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); #else return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName()); @@ -184,7 +195,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper @Override public String getDimensionName() { - #if MC_VER <= MC_1_21_10 + #if MC_VER <= MC_1_12_2 + return this.level.provider.getDimensionType().getName(); + #elif MC_VER <= MC_1_21_10 return this.level.dimension().location().toString(); #else return this.level.dimension().identifier().toString(); @@ -192,7 +205,14 @@ public class ServerLevelWrapper implements IServerLevelWrapper } @Override - public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; } + public long getHashedSeed() + { + #if MC_VER <= MC_1_12_2 + return this.level.getSeed(); + #else + return this.level.getBiomeManager().biomeZoomSeed; + #endif + } @Override public String getDhIdentifier() { return this.getDimensionName(); } @@ -200,13 +220,28 @@ public class ServerLevelWrapper implements IServerLevelWrapper @Override public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; } - public ServerLevel getLevel() { return this.level; } + public #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif getLevel() { return this.level; } @Override - public boolean hasCeiling() { return this.level.dimensionType().hasCeiling(); } + public boolean hasCeiling() + { + #if MC_VER <= MC_1_12_2 + // 1.12.2 has no hasCeiling() - only the nether has a ceiling in vanilla + return this.level.provider.isNether(); + #else + return this.level.dimensionType().hasCeiling(); + #endif + } @Override - public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); } + public boolean hasSkyLight() + { + #if MC_VER <= MC_1_12_2 + return this.level.provider.hasSkyLight(); + #else + return this.level.dimensionType().hasSkyLight(); + #endif + } @Override public int getMaxHeight() { return this.level.getHeight(); } @@ -224,7 +259,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper } @Override - public ServerLevel getWrappedMcObject() { return this.level; } + public #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif getWrappedMcObject() { return this.level; } @Override public void onUnload() { LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.remove(this.level); } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java index 454222ab8..01b7d919e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java @@ -26,8 +26,10 @@ import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGenerat import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.*; +#endif import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.api.internal.chunkUpdating.ChunkUpdateQueueManager; @@ -57,18 +59,26 @@ import com.seibel.distanthorizons.coreapi.ModInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepBiomes; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepNoise; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepStructureReference; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepStructureStart; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepSurface; +#endif +#if MC_VER <= MC_1_12_2 +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.ForgeChunkManager; +#else import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.*; import net.minecraft.world.level.levelgen.DebugLevelSource; import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +#endif + #if MC_VER <= MC_1_17_1 #elif MC_VER <= MC_1_19_2 @@ -80,12 +90,14 @@ import net.minecraft.core.registries.Registries; #else #endif - -#if MC_VER <= MC_1_20_4 +#if MC_VER <= MC_1_12_2 +#elif MC_VER <= MC_1_20_4 import net.minecraft.world.level.chunk.ChunkStatus; #else import net.minecraft.world.level.chunk.status.ChunkStatus; #endif +import org.jetbrains.annotations.Nullable; + public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironmentWrapper { @@ -122,7 +134,10 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm private final ChunkUpdateQueueManager updateManager; public final InternalServerGenerator internalServerGenerator; + + #if MC_VER > MC_1_12_2 public final ChunkFileReader chunkFileReader; + #endif private final Timer chunkSaveIgnoreTimer = TimerUtil.CreateTimer("ChunkSaveIgnoreTimer"); @@ -131,12 +146,14 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm public final LinkedBlockingQueue generationEventQueue = new LinkedBlockingQueue<>(); public final GlobalWorldGenParams globalParams; + #if MC_VER > MC_1_12_2 public final StepStructureStart stepStructureStart = new StepStructureStart(this); public final StepStructureReference stepStructureReference = new StepStructureReference(this); public final StepBiomes stepBiomes = new StepBiomes(this); public final StepNoise stepNoise = new StepNoise(this); public final StepSurface stepSurface = new StepSurface(this); public final StepFeatures stepFeatures = new StepFeatures(this); + #endif public boolean unsafeThreadingRecorded = false; public boolean generatedChunkWithoutBiomeWarningLogged = false; @@ -181,6 +198,8 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm this.updateManager = WorldChunkUpdateManager.INSTANCE.getByLevelWrapper(this.dhServerLevel.getServerLevelWrapper()); this.globalParams = new GlobalWorldGenParams(dhServerLevel); this.internalServerGenerator = new InternalServerGenerator(this.globalParams, this.dhServerLevel); + + #if MC_VER > MC_1_12_2 this.chunkFileReader = new ChunkFileReader(this.globalParams); ChunkGenerator generator = ((ServerLevelWrapper) (dhServerLevel.getServerLevelWrapper())).getLevel().getChunkSource().getGenerator(); @@ -201,6 +220,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "]."); } } + #endif } @@ -309,6 +329,11 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm // variable setup // //================// + #if MC_VER <= MC_1_12_2 + // MC 1.12 can only run world gen on the main thread + this.internalServerGenerator.generateChunksViaInternalServer(genEvent); + + #else int borderSize = MAX_WORLD_GEN_CHUNK_BORDER_NEEDED; // genEvent.size - 1 converts the even width size to an odd number for MC compatability int refSize = (genEvent.widthInChunks - 1) + (borderSize * 2); @@ -558,12 +583,14 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm { LOGGER.error("Unexpected error during world gen for min chunk pos ["+genEvent.minPos+"], error: ["+e.getMessage()+"].", e); } + #endif } // direct generation // + #if MC_VER > MC_1_12_2 public void generateDirect( GenerationEvent genEvent, ArrayGridList chunkWrappersToGenerate, DhLitWorldGenRegion region) throws InterruptedException @@ -728,7 +755,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm } private static ArrayGridList GetCutoutFrom(ArrayGridList total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); } private static ArrayGridList GetCutoutFrom(ArrayGridList total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); } - + #endif // queue task // @@ -769,8 +796,9 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm } + #if MC_VER > MC_1_12_2 this.chunkFileReader.close(); - + #endif } @@ -798,12 +826,12 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm // helper classes // //================// + #if MC_VER > MC_1_12_2 @FunctionalInterface public interface IEmptyChunkRetrievalFunc { ChunkAccess getChunk(int chunkPosX, int chunkPosZ); } + #endif - - -} \ No newline at end of file +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/ChunkPosGenStream.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/ChunkPosGenStream.java index a4e92348c..1ce3e7ee0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/ChunkPosGenStream.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/ChunkPosGenStream.java @@ -1,6 +1,10 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration; +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.math.ChunkPos; +#else import net.minecraft.world.level.ChunkPos; +#endif import java.util.Iterator; import java.util.Spliterator; diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/GenerationEvent.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/GenerationEvent.java index 603318235..ded0c34aa 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/GenerationEvent.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/GenerationEvent.java @@ -25,7 +25,9 @@ import java.util.function.Consumer; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams; +#endif import com.seibel.distanthorizons.core.util.ExceptionUtil; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhChunkPos; @@ -43,7 +45,9 @@ public final class GenerationEvent /** can be used for troubleshooting */ public final int id; + #if MC_VER > MC_1_12_2 public final ThreadWorldGenParams threadedParam; + #endif public final DhChunkPos minPos; public final int widthInChunks; public final EDhApiWorldGenerationStep targetGenerationStep; @@ -67,7 +71,9 @@ public final class GenerationEvent this.widthInChunks = widthInChunks; this.targetGenerationStep = targetGenerationStep; this.generatorMode = generatorMode; + #if MC_VER > MC_1_12_2 this.threadedParam = ThreadWorldGenParams.getOrMake(generationGroup.globalParams); + #endif this.future = new CompletableFuture<>(); this.resultConsumer = resultConsumer; } @@ -168,4 +174,4 @@ public final class GenerationEvent -} \ No newline at end of file +} diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/InternalServerGenerator.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/InternalServerGenerator.java index b2e6b9717..fc82afcc2 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/InternalServerGenerator.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/InternalServerGenerator.java @@ -15,6 +15,7 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.level.IDhServerLevel; import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.util.ExceptionUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.TimerUtil; @@ -23,14 +24,23 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IC2meAccess import com.seibel.distanthorizons.coreapi.ModInfo; import org.jetbrains.annotations.Nullable; - +#if MC_VER <= MC_1_12_2 +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.ChunkProviderServer; +import net.minecraftforge.common.ForgeChunkManager; +#else import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.TicketType; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; +#endif -#if MC_VER <= MC_1_20_4 +#if MC_VER <= MC_1_12_2 +#elif MC_VER <= MC_1_20_4 import net.minecraft.world.level.chunk.ChunkStatus; #else import net.minecraft.world.level.chunk.status.ChunkStatus; @@ -64,7 +74,8 @@ public class InternalServerGenerator */ private static final int MS_TO_IGNORE_CHUNK_AFTER_COMPLETION = 5_000; - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + #elif MC_VER < MC_1_21_5 private static final TicketType DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong)); #elif MC_VER < MC_1_21_9 private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* persist */ false, TicketType.TicketUse.LOADING); @@ -110,14 +121,14 @@ public class InternalServerGenerator // create gen requests // //=====================// - ArrayList> getChunkFutureList = new ArrayList<>(); + ArrayList> getChunkFutureList = new ArrayList<>(); { Iterator chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0); while (chunkPosIterator.hasNext()) { ChunkPos chunkPos = chunkPosIterator.next(); - CompletableFuture requestChunkFuture = + CompletableFuture<#if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif> requestChunkFuture = this.requestChunkFromServerAsync(chunkPos) // log errors if necessary .whenCompleteAsync( @@ -160,8 +171,8 @@ public class InternalServerGenerator ArrayList chunkWrappers = new ArrayList<>(); for (int i = 0; i < getChunkFutureList.size(); i++) { - CompletableFuture getChunkFuture = getChunkFutureList.get(i); - ChunkAccess chunk = getChunkFuture.join(); + CompletableFuture<#if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif> getChunkFuture = getChunkFutureList.get(i); + #if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif chunk = getChunkFuture.join(); if (chunk != null) { ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper()); @@ -245,8 +256,43 @@ public class InternalServerGenerator LOGGER.warn(c2meWarning); } } - private CompletableFuture requestChunkFromServerAsync(ChunkPos chunkPos) + private CompletableFuture<#if MC_VER <= MC_1_12_2 Chunk #else ChunkAccess #endif> requestChunkFromServerAsync(ChunkPos chunkPos) { + #if MC_VER <= MC_1_12_2 + WorldServer level = this.params.mcServerLevel; + + // ignore chunk update events for this position + if (this.updateManager != null) + { + this.updateManager.addPosToIgnore(McObjectConverter.Convert(chunkPos)); + } + + CompletableFuture future = new CompletableFuture<>(); + level.getMinecraftServer().addScheduledTask(() -> + { + ChunkProviderServer provider = level.getChunkProvider(); + + // load neighbours first so the target chunk can fully populate + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + if (i != 0 || j != 0) + { + if (this.updateManager != null) + { + this.updateManager.addPosToIgnore(new DhChunkPos(chunkPos.x + i, chunkPos.z + j)); + } + provider.provideChunk(chunkPos.x + i, chunkPos.z + j); + } + } + } + + Chunk chunk = provider.provideChunk(chunkPos.x, chunkPos.z); + future.complete(chunk); + }); + return future; + #else return CompletableFuture.supplyAsync(() -> { ServerLevel level = this.params.mcServerLevel; @@ -289,27 +335,55 @@ public class InternalServerGenerator }, this.params.mcServerLevel.getChunkSource().chunkMap.mainThreadExecutor) .thenCompose(Function.identity()); + #endif } /** * mitigates out of memory issues in the vanilla chunk system.
* See: https://github.com/pop4959/Chunky/pull/383 */ - private CompletableFuture releaseChunkFromServerAsync(ServerLevel level, ChunkPos chunkPos) + private CompletableFuture releaseChunkFromServerAsync(#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level, ChunkPos chunkPos) { CompletableFuture removeTicketFuture = new CompletableFuture<>(); - + #if MC_VER <= MC_1_12_2 + level.getMinecraftServer().addScheduledTask(() -> + #else level.getChunkSource().chunkMap.mainThreadExecutor.execute(() -> + #endif { try { - #if MC_VER < MC_1_21_5 + #if MC_VER <= MC_1_12_2 + for (int i = -1; i <= 1; i++) + { + for (int j = -1; j <= 1; j++) + { + if (i != 0 || j != 0) + { + final int di = i, dj = j; + this.chunkSaveIgnoreTimer.schedule(new TimerTask() + { + @Override + public void run() + { + if (InternalServerGenerator.this.updateManager != null) + { + InternalServerGenerator.this.updateManager.removePosToIgnore(new DhChunkPos(chunkPos.x + di, chunkPos.z + dj)); + } + } + }, MS_TO_IGNORE_CHUNK_AFTER_COMPLETION); + } + } + } + #elif MC_VER < MC_1_21_5 int chunkLevel = 33; // 33 is equivalent to FULL Chunk level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, chunkPos, chunkLevel, chunkPos); #else level.getChunkSource().removeTicketWithRadius(DH_SERVER_GEN_TICKET, chunkPos, 0); #endif + #if MC_VER > MC_1_12_2 level.getChunkSource().chunkMap.tick(() -> false); + #endif #if MC_VER > MC_1_16_5 level.entityManager.tick(); @@ -340,7 +414,6 @@ public class InternalServerGenerator removeTicketFuture.complete(null); } }); - return removeTicketFuture; } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkCompoundTagParser.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkCompoundTagParser.java index f19e145d5..a3381679a 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkCompoundTagParser.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkCompoundTagParser.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling; +#if MC_VER > MC_1_12_2 import com.mojang.serialization.Codec; import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; @@ -749,3 +750,4 @@ public class ChunkCompoundTagParser } +#endif diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkFileReader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkFileReader.java index 3ea80ceec..63a4f072e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkFileReader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/ChunkFileReader.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.RegionFileStorageExternalCache; @@ -341,3 +342,4 @@ public class ChunkFileReader implements AutoCloseable } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/CompoundTagUtil.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/CompoundTagUtil.java index f175815c8..2dd870807 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/CompoundTagUtil.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/chunkFileHandling/CompoundTagUtil.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling; +#if MC_VER > MC_1_12_2 import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import org.jetbrains.annotations.Nullable; @@ -146,3 +147,4 @@ public class CompoundTagUtil } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java index 8e16814a1..df42e7f98 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DhLitWorldGenRegion.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; +#if MC_VER > MC_1_12_2 import java.lang.invoke.MethodHandles; import java.util.List; import java.util.concurrent.locks.ReentrantLock; @@ -488,4 +489,5 @@ public class DhLitWorldGenRegion extends WorldGenRegion return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DummyLightEngine.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DummyLightEngine.java index 822e66d2c..069be50c8 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DummyLightEngine.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/DummyLightEngine.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; +#if MC_VER > MC_1_12_2 import net.minecraft.world.level.lighting.*; import org.jetbrains.annotations.Nullable; @@ -96,4 +97,5 @@ public class DummyLightEngine extends LevelLightEngine public int getMaxLightSection() { throw new UnsupportedOperationException("This should never be used!"); } #endif -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java index c6032ea00..ebe77cbe8 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/LightGetterAdaptor.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IStarlightAccessor; @@ -79,4 +80,5 @@ public class LightGetterAdaptor implements LightChunkGetter return heightGetter; } #endif -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/RegionFileStorageExternalCache.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/RegionFileStorageExternalCache.java index 28c899038..88a6d2778 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/RegionFileStorageExternalCache.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/RegionFileStorageExternalCache.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import net.minecraft.nbt.CompoundTag; @@ -250,3 +251,4 @@ public class RegionFileStorageExternalCache implements AutoCloseable } } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java index 2d55f3bdf..b2b58adee 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/WorldGenStructFeatManager.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; +#if MC_VER > MC_1_12_2 import java.util.Iterator; import java.util.List; import java.util.Map; @@ -277,3 +278,4 @@ public class WorldGenStructFeatManager extends #if MC_VER < MC_1_19_2 StructureF #endif #endif } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/GlobalWorldGenParams.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/GlobalWorldGenParams.java index 2bb89d8ba..68137faed 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/GlobalWorldGenParams.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/GlobalWorldGenParams.java @@ -19,10 +19,17 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.params; -import com.mojang.datafixers.DataFixer; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.core.level.IDhServerLevel; + +#if MC_VER <= MC_1_12_2 +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.datafix.DataFixer; +import net.minecraft.world.WorldServer; +import net.minecraft.world.gen.IChunkGenerator; +#else +import com.mojang.datafixers.DataFixer; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.server.MinecraftServer; @@ -56,30 +63,39 @@ import net.minecraft.world.level.levelgen.WorldGenSettings; #else import net.minecraft.world.level.levelgen.WorldOptions; #endif +#endif +#if MC_VER > MC_1_12_2 /** * Handles parameters that are relevant for the entire MC world. * * @see ThreadWorldGenParams */ +#endif + public final class GlobalWorldGenParams { - public final ChunkGenerator generator; + public final #if MC_VER <= MC_1_12_2 IChunkGenerator #else ChunkGenerator #endif generator; public final IDhServerLevel dhServerLevel; - public final ServerLevel mcServerLevel; + public final #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif mcServerLevel; + #if MC_VER > MC_1_12_2 public final Registry biomes; public final RegistryAccess registry; + #endif + public final long worldSeed; public final DataFixer dataFixer; - #if MC_VER < MC_1_19_2 + #if MC_VER <= MC_1_12_2 + #elif MC_VER < MC_1_19_2 public final StructureManager structures; #else public final StructureTemplateManager structures; public final RandomState randomState; #endif - #if MC_VER < MC_1_19_4 + #if MC_VER <= MC_1_12_2 + #elif MC_VER < MC_1_19_4 public final WorldGenSettings worldGenSettings; #else public final WorldOptions worldOptions; @@ -99,13 +115,17 @@ public final class GlobalWorldGenParams public GlobalWorldGenParams(IDhServerLevel dhServerLevel) { this.dhServerLevel = dhServerLevel; - this.mcServerLevel = ((ServerLevelWrapper) dhServerLevel.getServerLevelWrapper()).getWrappedMcObject(); - MinecraftServer server = this.mcServerLevel.getServer(); + + MinecraftServer server = this.mcServerLevel.#if MC_VER <= MC_1_12_2 getMinecraftServer() #else getServer() #endif; + #if MC_VER > MC_1_12_2 WorldData worldData = server.getWorldData(); this.registry = server.registryAccess(); + #endif - #if MC_VER < MC_1_19_4 + #if MC_VER <= MC_1_12_2 + this.worldSeed = mcServerLevel.getSeed(); + #elif MC_VER < MC_1_19_4 this.worldGenSettings = worldData.worldGenSettings(); this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY); this.worldSeed = worldGenSettings.seed(); @@ -123,15 +143,24 @@ public final class GlobalWorldGenParams this.worldSeed = this.worldOptions.seed(); #endif + #if MC_VER >= MC_1_18_2 this.biomeManager = new BiomeManager(this.mcServerLevel, BiomeManager.obfuscateSeed(this.worldSeed)); this.chunkScanner = this.mcServerLevel.getChunkSource().chunkScanner(); #endif + #if MC_VER <= MC_1_12_2 + this.generator = this.mcServerLevel.getChunkProvider().chunkGenerator; + #else this.structures = server.getStructureManager(); this.generator = this.mcServerLevel.getChunkSource().getGenerator(); - this.dataFixer = server.getFixerUpper(); + #endif + #if MC_VER <= MC_1_12_2 + this.dataFixer = server != null ? server.getDataFixer() : null; + #else + this.dataFixer = server.getFixerUpper(); + #endif #if MC_VER >= MC_1_19_2 this.randomState = this.mcServerLevel.getChunkSource().randomState(); #endif diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/ThreadWorldGenParams.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/ThreadWorldGenParams.java index 6e294d47c..afc7caf84 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/ThreadWorldGenParams.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/params/ThreadWorldGenParams.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.params; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager; import net.minecraft.server.level.ServerLevel; @@ -118,4 +119,5 @@ public final class ThreadWorldGenParams -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java index 4cf169062..161062d42 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/AbstractWorldGenStep.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; @@ -52,3 +53,4 @@ public abstract class AbstractWorldGenStep } +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java index 411d95be7..b4714115e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import java.util.ArrayList; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; @@ -114,4 +115,5 @@ public final class StepBiomes extends AbstractWorldGenStep } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java index 936f99b4b..b759ae4ce 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams; @@ -118,4 +119,5 @@ public final class StepFeatures extends AbstractWorldGenStep } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java index fd3b4677f..3bf62282f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepNoise.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import java.util.ArrayList; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; @@ -106,4 +107,5 @@ public final class StepNoise extends AbstractWorldGenStep } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java index 5fd9e7dfc..3e6bbd8ed 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import java.util.ArrayList; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; @@ -72,4 +73,5 @@ public final class StepStructureReference extends AbstractWorldGenStep } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java index ef70ea69b..1208bfa9f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import java.util.ArrayList; import java.util.concurrent.locks.ReentrantLock; @@ -142,4 +143,5 @@ public final class StepStructureStart extends AbstractWorldGenStep } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java index 839723999..316785d1e 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; +#if MC_VER > MC_1_12_2 import java.util.ArrayList; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; @@ -81,4 +82,5 @@ public final class StepSurface extends AbstractWorldGenStep -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/common/src/main/resources/1_12_2.distanthorizons_at.cfg b/common/src/main/resources/1_12_2.distanthorizons_at.cfg new file mode 100644 index 000000000..148f0fb86 --- /dev/null +++ b/common/src/main/resources/1_12_2.distanthorizons_at.cfg @@ -0,0 +1,3 @@ +public net.minecraft.client.renderer.EntityRenderer getFOVModifier(FZ)F +public net.minecraft.client.renderer.ActiveRenderInfo MODELVIEW +public net.minecraft.client.renderer.ActiveRenderInfo PROJECTION \ No newline at end of file diff --git a/compile.sh b/compile.sh deleted file mode 100644 index 9cc9a628b..000000000 --- a/compile.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -publish_version() -{ - if [[ "$2" == "all" || "$1" == "$2" ]] - then - docker run --name=dh-build-$1 --rm -v /${PWD}:/home/build -e MC_VER=$1 dh-eclipse-temurin - cp ./fabric/build/libs/*$1.jar ./buildAllJars/fabric/ - cp ./forge/build/libs/*$1.jar ./buildAllJars/forge/ - cp ./Merged/*.jar ./buildAllJars/merged/ - fi -} - - -if [ -z "$1" ] -then - echo "Build target is undefined! [all] [1.20.1] [1.19.4] [1.19.2] [1.18.2] [1.17.1] [1.16.5]" - exit 1 -fi - -docker build --tag=dh-eclipse-temurin -q . - -mkdir -p buildAllJars/fabric -mkdir -p buildAllJars/forge -mkdir -p buildAllJars/merged -publish_version 1.20.1 $1 -publish_version 1.19.4 $1 -publish_version 1.19.2 $1 -publish_version 1.18.2 $1 -publish_version 1.17.1 $1 -publish_version 1.16.5 $1 diff --git a/coreSubProjects b/coreSubProjects index 9fa9b430f..592b05093 160000 --- a/coreSubProjects +++ b/coreSubProjects @@ -1 +1 @@ -Subproject commit 9fa9b430f661036f17351d957c99d0f269b47e24 +Subproject commit 592b0509377b69f7446cd26c646c618f5c42e040 diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricServerProxy.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricServerProxy.java index cf0568fb5..3781fd8c8 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricServerProxy.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricServerProxy.java @@ -1,6 +1,8 @@ package com.seibel.distanthorizons.fabric; import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockColorOverrideEvent; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockStateWrapperCreatedEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkProcessingEvent; import com.seibel.distanthorizons.api.methods.events.DhApiEventRegister; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelLoadEvent; @@ -16,7 +18,9 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +import com.seibel.distanthorizons.fabric.testing.TestBlockWrapperCreatedEvent; import com.seibel.distanthorizons.fabric.testing.TestChunkInputReplacerEvent; +import com.seibel.distanthorizons.fabric.testing.TestCustomColorEvent; import com.seibel.distanthorizons.fabric.testing.TestWorldGenBindingEvent; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -87,11 +91,21 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy /* Register the mod needed event callbacks */ - // can be enabled to test overrides/events without having to build a separate API project - if (false) + // can be enabled to test overrides/events without having to build a separate API project { - DhApiEventRegister.on(DhApiLevelLoadEvent.class, new TestWorldGenBindingEvent()); - DhApi.events.bind(DhApiChunkProcessingEvent.class, new TestChunkInputReplacerEvent()); + // test custom world gen + if (false) + { + DhApiEventRegister.on(DhApiLevelLoadEvent.class, new TestWorldGenBindingEvent()); + DhApi.events.bind(DhApiChunkProcessingEvent.class, new TestChunkInputReplacerEvent()); + } + + // test custom colors + if (false) + { + DhApi.events.bind(DhApiBlockColorOverrideEvent.class, new TestCustomColorEvent()); + DhApi.events.bind(DhApiBlockStateWrapperCreatedEvent.class, new TestBlockWrapperCreatedEvent()); + } } diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/testing/TestBlockWrapperCreatedEvent.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/testing/TestBlockWrapperCreatedEvent.java new file mode 100644 index 000000000..d703fff5b --- /dev/null +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/testing/TestBlockWrapperCreatedEvent.java @@ -0,0 +1,43 @@ +package com.seibel.distanthorizons.fabric.testing; + +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockStateWrapperCreatedEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.core.logging.DhLogger; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.LodUtil; + +import java.util.Random; + +/** + * @see TestCustomColorEvent + */ +public class TestBlockWrapperCreatedEvent extends DhApiBlockStateWrapperCreatedEvent +{ + private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + + + + + @Override + public void blockStateWrapperCreated(DhApiEventParam event) + { + EventParam eventParam = event.value; + + // can be enabled to flip the opacity of transparent/opaque blocks + if (false) + { + if (eventParam.getBlockStateWrapper().getOpacity() == LodUtil.BLOCK_FULLY_OPAQUE) + { + eventParam.setOpacity(LodUtil.BLOCK_FULLY_TRANSPARENT); + } + else + { + eventParam.setOpacity(LodUtil.BLOCK_FULLY_OPAQUE); + } + } + + // needed for TestCustomColorEvent + eventParam.setAllowApiColorOverride(true); + } + +} diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/testing/TestCustomColorEvent.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/testing/TestCustomColorEvent.java new file mode 100644 index 000000000..7c08334ff --- /dev/null +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/testing/TestCustomColorEvent.java @@ -0,0 +1,86 @@ +package com.seibel.distanthorizons.fabric.testing; + +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockColorOverrideEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.core.logging.DhLogger; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; + +import java.awt.*; + +/** + * @see TestBlockWrapperCreatedEvent + */ +public class TestCustomColorEvent extends DhApiBlockColorOverrideEvent +{ + private static final DhLogger LOGGER = new DhLoggerBuilder().build(); + + + + @Override + public void blockStateWrapperCreated(DhApiEventParam event) + { + EventParam eventParam = event.value; + + //randomDatapointColors(eventParam); + //randomPerBlockColors(eventParam); + //blackWhitePositionStripe(eventParam); + positionRainbow(eventParam); + } + + /** each datapoint has a random color */ + private void randomDatapointColors(EventParam eventParam) + { + // random colors for each datapoint + int a = eventParam.getAlpha(); + int r = eventParam.getRed(); + int g = eventParam.getGreen(); + int b = eventParam.getBlue(); + + if (eventParam.getBlockStateWrapper().getOpacity() == LodUtil.BLOCK_FULLY_OPAQUE) + { + eventParam.setColor(255,r,g,b); + } + else + { + eventParam.setColor(60,r,g,b); + } + } + + /** each block has a different color */ + private void randomPerBlockColors(EventParam eventParam) + { + // random colors per block + int r = Math.abs(eventParam.getBlockStateWrapper().hashCode() % 255); + int g = Math.abs((eventParam.getBlockStateWrapper().hashCode() << 4) % 255); + int b = Math.abs((eventParam.getBlockStateWrapper().hashCode() << 8) % 255); + eventParam.setColor(r,g,b); + } + + private void blackWhitePositionStripe(EventParam eventParam) + { + // black-white stripes + int r = Math.abs(eventParam.getBlockPosX() % 255); + int g = r; + int b = r; + eventParam.setColor(r,g,b); + } + + /** rainbow along the X axis repeating every 255 blocks */ + private void positionRainbow(EventParam eventParam) + { + float[] ahsv = ColorUtil.argbToAhsv(ColorUtil.RED); + float a = ahsv[0]; + + int xModPos = Math.abs(eventParam.getBlockPosX() % 510); + float h = xModPos < 255 ? xModPos : 510 - xModPos; + float s = ahsv[2]; + float v = ahsv[3]; + int colorInt = ColorUtil.ahsvToArgb(a,h,s,v); + eventParam.setColor(ColorUtil.getRed(colorInt),ColorUtil.getGreen(colorInt),ColorUtil.getBlue(colorInt)); + } + + + +} diff --git a/forge/build.gradle b/forge/build.gradle index 33ba45e15..39913fb5b 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -18,10 +18,13 @@ def addMod(path, enabled) { dependencies { // TerraForged addMod("curse.maven:TerraForged-363820:${rootProject.terraforged_version}", rootProject.enable_terraforged) - + // TerraFirmaCraft addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft) - + + // Oculus (Iris port) + addMod("maven.modrinth:oculus:${rootProject.oculus_version}", rootProject.enable_oculus) + // TODO: Check if this is still needed and if so ensure this code works for MC 26.1+ // (potential) hack fix for MC 1.20.6 and later, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+ def mcParts = rootProject.minecraft_version.split("\\.") diff --git a/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinFogRenderer.java b/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinFogRenderer.java index e64fad35a..724f6e838 100644 --- a/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinFogRenderer.java +++ b/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinFogRenderer.java @@ -50,9 +50,12 @@ public class MixinFogRenderer #if MC_VER < MC_1_17_1 RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE); RenderSystem.fogEnd(A_EVEN_LARGER_VALUE); - #else + #elif MC_VER < MC_1_21_3 RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE); RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE); + #elif MC_VER < MC_1_21_6 + callback.setReturnValue(FogParameters.NO_FOG); + #else #endif ClientApi.RENDER_STATE.vanillaFogEnabled = false; @@ -61,6 +64,7 @@ public class MixinFogRenderer { ClientApi.RENDER_STATE.vanillaFogEnabled = true; } + } } diff --git a/forge/src/main/java/com/seibel/distanthorizons/forge/wrappers/modAccessor/OculusAccessor.java b/forge/src/main/java/com/seibel/distanthorizons/forge/wrappers/modAccessor/OculusAccessor.java index e0a031b66..adadd2ad8 100644 --- a/forge/src/main/java/com/seibel/distanthorizons/forge/wrappers/modAccessor/OculusAccessor.java +++ b/forge/src/main/java/com/seibel/distanthorizons/forge/wrappers/modAccessor/OculusAccessor.java @@ -23,35 +23,50 @@ import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor; +#if MC_VER == MC_1_20_1 +import net.irisshaders.iris.Iris; +import net.irisshaders.iris.api.v0.IrisApi; +#else +#endif + public class OculusAccessor implements IIrisAccessor { protected static final DhLogger LOGGER = new DhLoggerBuilder().build(); public OculusAccessor() - { - LOGGER.warn("Partial Oculus support enabled. Some DH features may be disabled or behave strangely, use Iris instead if possible."); - } + { LOGGER.warn("Partial Oculus support enabled. Some DH features may be disabled or behave strangely, use Iris instead if possible."); } @Override public String getModName() { - return "oculus"; + #if MC_VER == MC_1_20_1 + return Iris.MODID; + #else + return "iris"; // Oculus doesn't support this MC version + #endif } @Override public boolean isShaderPackInUse() { - // assume shaders are always active - return true; + #if MC_VER == MC_1_20_1 + return IrisApi.getInstance().isShaderPackInUse(); + #else + return true; // Oculus doesn't support this MC version + #endif } @Override public boolean isRenderingShadowPass() { - return false; + #if MC_VER == MC_1_20_1 + return IrisApi.getInstance().isRenderingShadowPass(); + #else + return false; // Oculus doesn't support this MC version + #endif } } diff --git a/gradle.properties b/gradle.properties index 9ca5b4bc9..38f2d23ff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,10 +6,11 @@ org.gradle.caching=true # Mod Info mod_name=DistantHorizons api_name=DistantHorizonsApi -mod_version=3.0.3-b-dev -api_version=6.1.0 +mod_version=3.0.4-b-dev +api_version=6.1.1 maven_group=com.seibel.distanthorizons mod_readable_name=Distant Horizons +mod_id=distanthorizons mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow. # Note: In forge's mods.toml this is hard coded because Architectury throws an error with setting it as a variable mod_authors=["James Seibel", "Leonardo Amato", "Cola", "coolGi", "Ran", "Leetom", "pshsh"] @@ -47,7 +48,10 @@ versionStr= # This defines what MC version Intellij will use for the preprocessor # and what version is used automatically by build and run commands -mcVer=26.1.2 +mcVer=1.12.2 # Defines the maximum amount of memory Minecraft is allowed when run in a development environment minecraftMemoryJavaArg=-Xmx6G +# can be enabled for use with the Tracy profiler, disabled by default since it causes constant memory growth when running +minecraftEnableTracy=false + diff --git a/versionProperties/1.12.2.properties b/versionProperties/1.12.2.properties new file mode 100644 index 000000000..48ab26d05 --- /dev/null +++ b/versionProperties/1.12.2.properties @@ -0,0 +1,65 @@ +# 1.12.2 version +java_version=25 +minecraft_version=1.12.2 +parchment_version= +compatible_minecraft_versions=["1.12.2"] +accessWidenerVersion=1_12_2 +builds_for=cleanroom +embed_joml=true + +# Netty +netty_version=4.1.9.Final + +# LWJGL +lwjgl_version=3.3.6 + +# Cleanroom loader +cleanroom_loader_version=0.5.6-alpha + +# Fabric loader +fabric_loader_version= +fabric_api_version= + # Fabric mod versions + modmenu_version= + starlight_version_fabric= + phosphor_version_fabric= + lithium_version= + sodium_version= + iris_version= + bclib_version= + immersive_portals_version= + canvas_version= + + fabric_incompatibility_list={} + fabric_recommend_list={} + + # Fabric mod run + # 0 = Don't enable and don't run + # 1 = Can be referenced in code but doesn't run + # 2 = Can be referenced in code and runs in client + enable_mod_menu=0 + enable_starlight=0 + enable_phosphor=0 + enable_lithium=0 + enable_sodium=0 + enable_iris=0 + # not available via github, use curse.maven if necessary + enable_bclib=0 + enable_immersive_portals=0 + enable_canvas=0 + +# Forge loader +forge_version= + # Neo not used but the variable still needs to be defined to make gradle happy + neoforge_version_range=[*,) + + # Forge mod versions + terraforged_version= + + # Forge mod run + # 0 = Don't enable and don't run + # 1 = Can be referenced in code but doesn't run + # 2 = Can be referenced in code and runs in client + enable_starlight_forge=0 + enable_terraforged=0 + enable_terrafirmacraft=0 diff --git a/versionProperties/1.16.5.properties b/versionProperties/1.16.5.properties index a385e9199..d91c5b034 100644 --- a/versionProperties/1.16.5.properties +++ b/versionProperties/1.16.5.properties @@ -52,6 +52,7 @@ forge_version=36.2.39 # Forge mod versions terraforged_version=4044290 + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -60,3 +61,4 @@ forge_version=36.2.39 enable_starlight_forge=0 enable_terraforged=1 enable_terrafirmacraft=0 + enable_oculus=0 diff --git a/versionProperties/1.17.1.properties b/versionProperties/1.17.1.properties index e9cedb8cc..a7b0aabbe 100644 --- a/versionProperties/1.17.1.properties +++ b/versionProperties/1.17.1.properties @@ -51,6 +51,7 @@ forge_version=37.1.1 # Forge mod versions terraforged_version= + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -59,3 +60,4 @@ forge_version=37.1.1 enable_starlight_forge=0 enable_terraforged=0 enable_terrafirmacraft=0 + enable_oculus=0 diff --git a/versionProperties/1.18.2.properties b/versionProperties/1.18.2.properties index 605304d19..893ba78ef 100644 --- a/versionProperties/1.18.2.properties +++ b/versionProperties/1.18.2.properties @@ -60,6 +60,7 @@ forge_version=40.2.10 # Forge mod versions terraforged_version= + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -67,4 +68,5 @@ forge_version=40.2.10 # 2 = Can be referenced in code and runs in client enable_starlight_forge=0 enable_terraforged=0 - enable_terrafirmacraft=0 \ No newline at end of file + enable_terrafirmacraft=0 + enable_oculus=0 diff --git a/versionProperties/1.19.2.properties b/versionProperties/1.19.2.properties index 6c63fa21d..7f47277fe 100644 --- a/versionProperties/1.19.2.properties +++ b/versionProperties/1.19.2.properties @@ -50,6 +50,7 @@ forge_version=43.3.2 # Forge mod versions terraforged_version= + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -58,3 +59,4 @@ forge_version=43.3.2 enable_starlight_forge=0 enable_terraforged=0 enable_terrafirmacraft=0 + enable_oculus=0 diff --git a/versionProperties/1.19.4.properties b/versionProperties/1.19.4.properties index aba05c0ef..92e47fb93 100644 --- a/versionProperties/1.19.4.properties +++ b/versionProperties/1.19.4.properties @@ -49,6 +49,7 @@ forge_version=45.2.4 # Forge mod versions terraforged_version= + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -57,3 +58,4 @@ forge_version=45.2.4 enable_starlight_forge=0 enable_terraforged=0 enable_terrafirmacraft=0 + enable_oculus=0 diff --git a/versionProperties/1.20.1.properties b/versionProperties/1.20.1.properties index 1fb4fd4d6..137377adc 100644 --- a/versionProperties/1.20.1.properties +++ b/versionProperties/1.20.1.properties @@ -43,12 +43,13 @@ fabric_api_version=0.92.6+1.20.1 enable_canvas=0 # Forge loader -forge_version=47.2.1 +forge_version=47.4.20 # Neo not used but the variable still needs to be defined to make gradle happy neoforge_version_range=[*,) # Forge mod versions terraforged_version= + oculus_version=1.20.1-1.8.0 # Forge mod run # 0 = Don't enable and don't run @@ -57,3 +58,4 @@ forge_version=47.2.1 enable_starlight_forge=0 enable_terraforged=0 enable_terrafirmacraft=0 + enable_oculus=1 diff --git a/versionProperties/1.20.2.properties b/versionProperties/1.20.2.properties index baca60aa7..1d9b77fa1 100644 --- a/versionProperties/1.20.2.properties +++ b/versionProperties/1.20.2.properties @@ -49,6 +49,7 @@ forge_version=48.0.13 # Forge mod versions terraforged_version= + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -57,3 +58,4 @@ forge_version=48.0.13 enable_starlight_forge=0 enable_terraforged=0 enable_terrafirmacraft=0 + enable_oculus=0 diff --git a/versionProperties/1.20.4.properties b/versionProperties/1.20.4.properties index 04f58350c..de20e9aa3 100644 --- a/versionProperties/1.20.4.properties +++ b/versionProperties/1.20.4.properties @@ -44,12 +44,13 @@ fabric_api_version=0.91.2+1.20.4 enable_canvas=0 # Forge loader -forge_version=49.1.13 +forge_version=49.2.7 neoforge_version= neoforge_version_range=[*,) # Forge mod versions terraforged_version= + oculus_version= # Forge mod run # 0 = Don't enable and don't run @@ -58,3 +59,4 @@ neoforge_version= enable_starlight_forge=0 enable_terraforged=0 enable_terrafirmacraft=0 + enable_oculus=0