Compare commits
154 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d2e7524ae | |||
| e8ff7abaea | |||
| 008ad52bbc | |||
| d0b44a1ffc | |||
| 4ffe430686 | |||
| 19ca97c6c1 | |||
| 3334394bfd | |||
| 180e7cd814 | |||
| 84cf4505f2 | |||
| 1d74eea3ef | |||
| 6ee2e6be25 | |||
| b5c47d67cb | |||
| ead59d0817 | |||
| 1c9229c8f1 | |||
| 968a14c6a5 | |||
| 851c7439d5 | |||
| c902357a8f | |||
| 63170078f5 | |||
| d0dd1f125b | |||
| 32950d793e | |||
| 54e9bad907 | |||
| bb4ac770bd | |||
| 16afada6e9 | |||
| 7d0785a5fa | |||
| 6a67df462b | |||
| 0c45c76ff8 | |||
| bcb442e38d | |||
| 977ae471ea | |||
| b1701ab0d0 | |||
| c048d5cb56 | |||
| 2702f742d6 | |||
| 7add025c8a | |||
| 9dc220feb2 | |||
| 79955252c9 | |||
| bf13cc48a3 | |||
| cf454c80d7 | |||
| e6404cd882 | |||
| 52e64dc403 | |||
| 7c858afc5d | |||
| a44a5d7465 | |||
| f2d373b779 | |||
| 5138af0b78 | |||
| 37e99cd0a5 | |||
| 6cb8cd2bd9 | |||
| c5ae7da96c | |||
| 59b886c5e3 | |||
| 01e78f249f | |||
| e1c3da59db | |||
| cdfb46b041 | |||
| f944fe4409 | |||
| c2e45f3d65 | |||
| a9c4f3ea46 | |||
| 204d48517b | |||
| 759ec3676c | |||
| 8d2b5fa3ce | |||
| 2851b2c2db | |||
| e5ea86bf8f | |||
| 533c6a7f93 | |||
| ff41e070fd | |||
| b3f607e132 | |||
| 9ecbb9cc9f | |||
| 7888de8200 | |||
| d2327ae836 | |||
| ea92a8f922 | |||
| 47e97630b4 | |||
| c518345bcd | |||
| c250a7408e | |||
| 30da01f580 | |||
| 2c71c2bf76 | |||
| 13a4505d7d | |||
| 7f0eeb9f15 | |||
| d7eabcf3a6 | |||
| 7047d0afdf | |||
| f318b52280 | |||
| f50613e20c | |||
| af3a993042 | |||
| ace1aab42e | |||
| 350d72b6ec | |||
| 986a6cdc19 | |||
| 2aa8d9f489 | |||
| 5652a9328c | |||
| b7253b6549 | |||
| e026cf104c | |||
| ab4a9cbb55 | |||
| a709ab6071 | |||
| 3c11a2dc33 | |||
| ce2aa6602a | |||
| 738aff8ec6 | |||
| 91da0bf252 | |||
| af8dea9d9f | |||
| 384933d351 | |||
| a5344d50c2 | |||
| 2b4c5b91a4 | |||
| 3090544b85 | |||
| 75e1bbbe17 | |||
| 31b604b5c8 | |||
| 70ba93abec | |||
| f628a7f21e | |||
| 254f51ea5e | |||
| d44152dc46 | |||
| 0ef979ee6c | |||
| f67fb1758d | |||
| cf643372b6 | |||
| dc1a117f6b | |||
| 2545c7e76d | |||
| 506ba05b34 | |||
| 70be3f9364 | |||
| 8d9b5f66fa | |||
| 3a01151137 | |||
| 197051747a | |||
| 45efeb96fa | |||
| e05dff3fb9 | |||
| aec28854a3 | |||
| 106d97e0a1 | |||
| 63acd94fd4 | |||
| 34412305d0 | |||
| 6a418de153 | |||
| 41c6b2936b | |||
| 97130d1535 | |||
| d61dcfaab6 | |||
| 3c3f1ef41b | |||
| ed1d6396fd | |||
| 518ec18362 | |||
| 5715cd9266 | |||
| 56953efabc | |||
| 351802de4c | |||
| f60e74c838 | |||
| 2007a6af24 | |||
| 4bc199fe14 | |||
| bcd9a0da2c | |||
| 50c97e3ca3 | |||
| 7539cb94d4 | |||
| 3a20329096 | |||
| 702002c540 | |||
| 7f790e2c9c | |||
| b3f8b03fdf | |||
| 3597d69fa4 | |||
| ab10265150 | |||
| 671ee84136 | |||
| c489cebae3 | |||
| e55eeda1ac | |||
| 0086f40053 | |||
| 71bb151e61 | |||
| a71ceac15d | |||
| ada36c34c7 | |||
| 3cfb4386d9 | |||
| 352d0f4759 | |||
| d158a89592 | |||
| 9cc826f8a9 | |||
| 22a4c6bc79 | |||
| 20b9f4f1cb | |||
| 5c0c1c5e20 | |||
| c84ee721e3 | |||
| c46c056980 |
+1
-1
@@ -11,7 +11,7 @@ insert_final_newline = false
|
|||||||
max_line_length = 1000
|
max_line_length = 1000
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
ij_continuation_indent_size = 8
|
ij_continuation_indent_size = 4
|
||||||
ij_formatter_off_tag = @formatter:off
|
ij_formatter_off_tag = @formatter:off
|
||||||
ij_formatter_on_tag = @formatter:on
|
ij_formatter_on_tag = @formatter:on
|
||||||
ij_formatter_tags_enabled = true
|
ij_formatter_tags_enabled = true
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ build:
|
|||||||
parallel:
|
parallel:
|
||||||
matrix:
|
matrix:
|
||||||
- MC_VER: [
|
- MC_VER: [
|
||||||
"1.21.10", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1",
|
"1.21.11", "1.21.10", "1.21.9", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1",
|
||||||
"1.20.6", "1.20.4", "1.20.2", "1.20.1",
|
"1.20.6", "1.20.4", "1.20.2", "1.20.1",
|
||||||
"1.19.4", "1.19.2",
|
"1.19.4", "1.19.2",
|
||||||
"1.18.2",
|
"1.18.2",
|
||||||
|
|||||||
@@ -1,3 +1,37 @@
|
|||||||
Before creating an issue, please select the appropriate template from the dropdown above.
|
## Check off each item in this list before submitting:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
To mark a section as complete either put an "x" in between the square brackets, example: "[x]"
|
||||||
|
Or click the checkbox once the issue has been created.
|
||||||
|
-->
|
||||||
|
|
||||||
|
1. [ ] Check the FAQ to see if your issue has already been reported and has a solution:
|
||||||
|
[Problems-and-solutions](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions)
|
||||||
|
|
||||||
|
2. [ ] Make sure you are not using any mods on the incompatible list:
|
||||||
|
[Mod support FAQ](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/4-mod-support/Mod-Support)
|
||||||
|
|
||||||
|
3. [ ] Check the existing issues to verify that your bug hasn't already been submitted:
|
||||||
|
[Issues](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues)
|
||||||
|
|
||||||
|
4. [ ] Upload Minecraft's crash report and/or log. \
|
||||||
|
Minecraft crash reports are located in: `.minecraft/crash-reports` \
|
||||||
|
Minecraft logs are located in: `.minecraft/logs`
|
||||||
|
|
||||||
|
5. [ ] Upload your Distant Horizons Config. \
|
||||||
|
The config is found in: `.minecraft/configs/DistantHorizons.toml`
|
||||||
|
|
||||||
|
6. [ ] Fill out the information below:
|
||||||
|
|
||||||
|
* **minecraft version**:
|
||||||
|
|
||||||
|
* **Distant Horizons version**:
|
||||||
|
|
||||||
|
* **Mod loader**:
|
||||||
|
|
||||||
|
* **Installed mods (list the smallest number of mods that you can use to re-create the bug)**:
|
||||||
|
|
||||||
|
* **Describe the bug**:
|
||||||
|
|
||||||
|
* **Steps to reproduce the bug**:
|
||||||
|
|
||||||
The template will walk you through submitting a bug, feature, or improvement request.
|
|
||||||
|
|||||||
+41
-10
@@ -5,6 +5,9 @@ import org.apache.tools.zip.ZipEntry
|
|||||||
import javax.annotation.Nonnull
|
import javax.annotation.Nonnull
|
||||||
import org.apache.tools.zip.ZipOutputStream
|
import org.apache.tools.zip.ZipOutputStream
|
||||||
|
|
||||||
|
import java.util.function.Function
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id "java"
|
||||||
@@ -19,7 +22,7 @@ plugins {
|
|||||||
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
|
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
|
||||||
|
|
||||||
// Architectury is used here only as a replacement for forge's own loom
|
// Architectury is used here only as a replacement for forge's own loom
|
||||||
id "dev.architectury.loom" version "1.11-SNAPSHOT" apply false
|
id "dev.architectury.loom" version "1.13-SNAPSHOT" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,12 +76,23 @@ writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
|
|||||||
rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm")
|
rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm")
|
||||||
|
|
||||||
class NativeTransformer implements Transformer {
|
class NativeTransformer implements Transformer {
|
||||||
|
private Predicate<String> fileMatcher
|
||||||
|
private Function<String, String> filePathMapper
|
||||||
|
|
||||||
private final HashMap<String, String> replacements = new HashMap()
|
private final HashMap<String, String> replacements = new HashMap()
|
||||||
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||||
private var nativeRelocator
|
private var nativeRelocator
|
||||||
|
|
||||||
public File rootDir
|
public File rootDir
|
||||||
|
|
||||||
|
void matchFiles(Predicate<String> matcher) {
|
||||||
|
fileMatcher = matcher
|
||||||
|
}
|
||||||
|
|
||||||
|
void mapPaths(Function<String, String> mapper) {
|
||||||
|
filePathMapper = mapper
|
||||||
|
}
|
||||||
|
|
||||||
void relocateNative(String target, String replacement) {
|
void relocateNative(String target, String replacement) {
|
||||||
if (replacement.length() > target.length()) {
|
if (replacement.length() > target.length()) {
|
||||||
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||||
@@ -89,9 +103,7 @@ class NativeTransformer implements Transformer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||||
return replacements.keySet().stream().anyMatch {
|
return fileMatcher.test(element.name)
|
||||||
element.name.startsWith(it as String)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -103,11 +115,9 @@ class NativeTransformer implements Transformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map.Entry<String, String> pathReplacement = replacements.entrySet().stream().filter {
|
String path = filePathMapper != null
|
||||||
context.path.startsWith(it.key as String)
|
? filePathMapper.apply(context.path)
|
||||||
}.findFirst().orElseThrow()
|
: context.path
|
||||||
|
|
||||||
String path = context.path.replace(pathReplacement.key as String, pathReplacement.value as String)
|
|
||||||
content = nativeRelocator.processBinary(path, content, replacements)
|
content = nativeRelocator.processBinary(path, content, replacements)
|
||||||
|
|
||||||
rewrittenFiles.put(path, content)
|
rewrittenFiles.put(path, content)
|
||||||
@@ -248,7 +258,7 @@ subprojects { p ->
|
|||||||
// We cannot relocate this library since we call some MC classes that reference it
|
// We cannot relocate this library since we call some MC classes that reference it
|
||||||
implementation("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
|
implementation("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
|
||||||
|
|
||||||
forgeShadowMe("com.github.luben:zstd-jni:1.5.7-4")
|
forgeShadowMe("com.github.luben:zstd-jni:${rootProject.zstd_version}")
|
||||||
|
|
||||||
// Compression
|
// Compression
|
||||||
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
forgeShadowMe("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
|
||||||
@@ -351,9 +361,30 @@ subprojects { p ->
|
|||||||
|
|
||||||
transform(NativeTransformer) {
|
transform(NativeTransformer) {
|
||||||
rootDir = project.rootDir
|
rootDir = project.rootDir
|
||||||
|
|
||||||
|
matchFiles { it.startsWith("org/sqlite") }
|
||||||
|
mapPaths { it.replace("org/sqlite", "dh_sqlite") }
|
||||||
|
|
||||||
relocateNative "org/sqlite", "dh_sqlite"
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
relocateNative "org_sqlite", "dh_1sqlite"
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ZStd
|
||||||
|
// librariesLocation isn't used because it's too long for replacing paths in native libraries
|
||||||
|
// Allowing strings larger than the original string would require shifting the entire binary's contents
|
||||||
|
relocate "com.github.luben", "dhcomgithubluben"
|
||||||
|
relocate "libzstd-jni", "libzstd-jni_dh"
|
||||||
|
relocate "zstd-jni", "zstd-jni_dh"
|
||||||
|
|
||||||
|
transform(NativeTransformer) {
|
||||||
|
rootDir = project.rootDir
|
||||||
|
|
||||||
|
matchFiles { it.contains("libzstd-jni") && !it.contains("aix/ppc64") }
|
||||||
|
mapPaths { it.replace("libzstd-jni", "libzstd-jni_dh") }
|
||||||
|
|
||||||
|
relocateNative "com/github/luben", "dhcomgithubluben"
|
||||||
|
relocateNative "com_github_luben", "dhcomgithubluben"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// JOML
|
// JOML
|
||||||
|
|||||||
+27
-17
@@ -10,10 +10,11 @@ import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapp
|
|||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
|
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.enums.EMinecraftColor;
|
||||||
import com.seibel.distanthorizons.core.jar.ModJarInfo;
|
import com.seibel.distanthorizons.core.jar.ModJarInfo;
|
||||||
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
@@ -24,9 +25,8 @@ import com.seibel.distanthorizons.coreapi.ModInfo;
|
|||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ import java.util.function.Supplier;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractModInitializer
|
public abstract class AbstractModInitializer
|
||||||
{
|
{
|
||||||
protected static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
protected static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
private CommandInitializer commandInitializer;
|
private CommandInitializer commandInitializer;
|
||||||
|
|
||||||
@@ -46,7 +46,8 @@ public abstract class AbstractModInitializer
|
|||||||
// abstract methods //
|
// abstract methods //
|
||||||
//==================//
|
//==================//
|
||||||
|
|
||||||
protected abstract void createInitialBindings();
|
protected abstract void createInitialSharedBindings();
|
||||||
|
protected abstract void createInitialClientBindings();
|
||||||
protected abstract IEventProxy createClientProxy();
|
protected abstract IEventProxy createClientProxy();
|
||||||
protected abstract IEventProxy createServerProxy(boolean isDedicated);
|
protected abstract IEventProxy createServerProxy(boolean isDedicated);
|
||||||
protected abstract void initializeModCompat();
|
protected abstract void initializeModCompat();
|
||||||
@@ -66,6 +67,7 @@ public abstract class AbstractModInitializer
|
|||||||
public void onInitializeClient()
|
public void onInitializeClient()
|
||||||
{
|
{
|
||||||
DependencySetup.createClientBindings();
|
DependencySetup.createClientBindings();
|
||||||
|
this.createInitialClientBindings();
|
||||||
|
|
||||||
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client, firing DhApiBeforeDhInitEvent...");
|
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client, firing DhApiBeforeDhInitEvent...");
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||||
@@ -84,7 +86,7 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
// debug screen rendering handled via a mixin
|
// debug screen rendering handled via a mixin
|
||||||
#else
|
#else
|
||||||
DhDebugScreenEntry.register();
|
DhDebugScreenEntry.register();
|
||||||
@@ -113,8 +115,8 @@ public abstract class AbstractModInitializer
|
|||||||
this.initializeModCompat();
|
this.initializeModCompat();
|
||||||
|
|
||||||
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
|
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
|
||||||
|
this.commandInitializer = new CommandInitializer();
|
||||||
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer = new CommandInitializer(dispatcher); });
|
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer.initCommands(dispatcher); });
|
||||||
|
|
||||||
this.subscribeServerStartingEvent(server ->
|
this.subscribeServerStartingEvent(server ->
|
||||||
{
|
{
|
||||||
@@ -122,7 +124,7 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
this.initConfig();
|
this.initConfig();
|
||||||
this.postInit();
|
this.postInit();
|
||||||
this.commandInitializer.initCommands();
|
this.commandInitializer.onServerReady();
|
||||||
|
|
||||||
this.checkForUpdates();
|
this.checkForUpdates();
|
||||||
|
|
||||||
@@ -140,7 +142,7 @@ public abstract class AbstractModInitializer
|
|||||||
{
|
{
|
||||||
DependencySetup.createSharedBindings();
|
DependencySetup.createSharedBindings();
|
||||||
SharedApi.init();
|
SharedApi.init();
|
||||||
this.createInitialBindings();
|
this.createInitialSharedBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logBuildInfo()
|
private void logBuildInfo()
|
||||||
@@ -164,12 +166,17 @@ public abstract class AbstractModInitializer
|
|||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
ModAccessorInjector.INSTANCE.bind((Class<? extends IModAccessor>) accessorClass, accessorConstructor.get());
|
ModAccessorInjector.INSTANCE.bind((Class<? extends IModAccessor>) accessorClass, accessorConstructor.get());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.debug("Skipping mod compatibility accessor for: ["+modId+"]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initConfig()
|
private void initConfig()
|
||||||
{
|
{
|
||||||
ConfigBase.RunFirstTimeSetup();
|
ConfigHandler.tryRunFirstTimeSetup();
|
||||||
Config.completeDelayedSetup();
|
Config.completeDelayedSetup();
|
||||||
|
DhLogger.runDelayedConfigSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForUpdates()
|
private void checkForUpdates()
|
||||||
@@ -190,6 +197,12 @@ public abstract class AbstractModInitializer
|
|||||||
{
|
{
|
||||||
LOGGER.info("Running Delayed setup...");
|
LOGGER.info("Running Delayed setup...");
|
||||||
this.runDelayedSetup();
|
this.runDelayedSetup();
|
||||||
|
|
||||||
|
if (ConfigHandler.INSTANCE == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Config was not initialized. Make sure to call LodCommonMain.initConfig() before calling this method.");
|
||||||
|
}
|
||||||
|
|
||||||
LOGGER.info("Delayed setup complete, firing DhApiAfterDhInitEvent event...");
|
LOGGER.info("Delayed setup complete, firing DhApiAfterDhInitEvent event...");
|
||||||
|
|
||||||
// should be fired after all delayed setup so singletons and config can be accessed
|
// should be fired after all delayed setup so singletons and config can be accessed
|
||||||
@@ -227,8 +240,7 @@ public abstract class AbstractModInitializer
|
|||||||
if (showChatWarnings)
|
if (showChatWarnings)
|
||||||
{
|
{
|
||||||
String message =
|
String message =
|
||||||
// orange text
|
EMinecraftColor.ORANGE + "Distant Horizons: Alex's Cave detected." + EMinecraftColor.CLEAR_FORMATTING +
|
||||||
"\u00A76" + "Distant Horizons: Alex's Cave detected." + "\u00A7r\n" +
|
|
||||||
"You may have to change Alex's config for DH to render. ";
|
"You may have to change Alex's config for DH to render. ";
|
||||||
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
}
|
}
|
||||||
@@ -250,8 +262,7 @@ public abstract class AbstractModInitializer
|
|||||||
if (showChatWarnings)
|
if (showChatWarnings)
|
||||||
{
|
{
|
||||||
String message =
|
String message =
|
||||||
// orange text
|
EMinecraftColor.ORANGE + "Distant Horizons: WWOO detected." + EMinecraftColor.CLEAR_FORMATTING + "\n" +
|
||||||
"\u00A76" + "Distant Horizons: WWOO detected." + "\u00A7r\n" +
|
|
||||||
wwooWarning;
|
wwooWarning;
|
||||||
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
}
|
}
|
||||||
@@ -281,8 +292,7 @@ public abstract class AbstractModInitializer
|
|||||||
if (showChatWarnings)
|
if (showChatWarnings)
|
||||||
{
|
{
|
||||||
String message =
|
String message =
|
||||||
// orange text
|
EMinecraftColor.ORANGE + "Distant Horizons: Chunky detected." + EMinecraftColor.CLEAR_FORMATTING + "\n" +
|
||||||
"\u00A76" + "Distant Horizons: Chunky detected." + "\u00A7r\n" +
|
|
||||||
chunkyWarning;
|
chunkyWarning;
|
||||||
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-8
@@ -1,8 +1,8 @@
|
|||||||
package com.seibel.distanthorizons.common;
|
package com.seibel.distanthorizons.common;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
|
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
|
||||||
import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent;
|
import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent;
|
||||||
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
|
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
|
||||||
@@ -13,22 +13,29 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapp
|
|||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import io.netty.buffer.ByteBufUtil;
|
import io.netty.buffer.ByteBufUtil;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||||
{
|
{
|
||||||
private static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(),
|
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
() -> Config.Common.Logging.logNetworkEvent.get());
|
.fileLevelConfig(Config.Common.Logging.logNetworkEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
#if MC_VER >= MC_1_21_1
|
#if 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);
|
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||||
#else
|
#else
|
||||||
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
public static final Identifier WRAPPER_PACKET_RESOURCE = Identifier.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// "Forge byte" is an unused packet ID. We have our own system which works with all mod loaders,
|
// "Forge byte" is an unused packet ID. We have our own system which works with all mod loaders,
|
||||||
|
|||||||
+49
-14
@@ -3,36 +3,71 @@ package com.seibel.distanthorizons.common.commands;
|
|||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
|
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
|
||||||
import static net.minecraft.commands.Commands.literal;
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
/**
|
#if MC_VER <= MC_1_21_10
|
||||||
* Initializes commands of the mod.
|
#else
|
||||||
*/
|
import net.minecraft.server.permissions.PermissionCheck;
|
||||||
|
import net.minecraft.server.permissions.Permissions;
|
||||||
|
#endif
|
||||||
|
|
||||||
public class CommandInitializer
|
public class CommandInitializer
|
||||||
{
|
{
|
||||||
private final CommandDispatcher<CommandSourceStack> commandDispatcher;
|
private boolean serverReady = false;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
private static final int REQUIRED_PERMISSION_LEVEL = 4;
|
||||||
|
#else
|
||||||
|
private static final PermissionCheck COMMAND_PERMISSION_CHECK = new PermissionCheck.Require(Permissions.COMMANDS_OWNER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new instance of this class.
|
* A received command dispatcher, which is held until the server is ready to initialize the commands.
|
||||||
*
|
|
||||||
* @param commandDispatcher The dispatcher to use for registering commands.
|
|
||||||
*/
|
*/
|
||||||
public CommandInitializer(CommandDispatcher<CommandSourceStack> commandDispatcher)
|
@Nullable
|
||||||
|
private CommandDispatcher<CommandSourceStack> commandDispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the command initializer that the game is ready to accept commands.
|
||||||
|
* If {@link CommandInitializer#initCommands(CommandDispatcher)} has been fired before it was ready, it will also initialize the commands.
|
||||||
|
*/
|
||||||
|
public void onServerReady()
|
||||||
{
|
{
|
||||||
this.commandDispatcher = commandDispatcher;
|
this.serverReady = true;
|
||||||
|
if (this.commandDispatcher != null)
|
||||||
|
{
|
||||||
|
this.initCommands(this.commandDispatcher);
|
||||||
|
this.commandDispatcher = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all available commands.
|
* Initializes all available commands.
|
||||||
|
* If the game is not ready yet, it stores the dispatcher to initialize the commands later.
|
||||||
|
*
|
||||||
|
* @param commandDispatcher The command dispatcher to register commands to.
|
||||||
*/
|
*/
|
||||||
public void initCommands()
|
public void initCommands(CommandDispatcher<CommandSourceStack> commandDispatcher)
|
||||||
{
|
{
|
||||||
|
if (!this.serverReady)
|
||||||
|
{
|
||||||
|
this.commandDispatcher = commandDispatcher;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LiteralArgumentBuilder<CommandSourceStack> builder = literal("dh")
|
LiteralArgumentBuilder<CommandSourceStack> builder = literal("dh")
|
||||||
.requires(source -> source.hasPermission(4));
|
.requires((source) ->
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
return source.hasPermission(REQUIRED_PERMISSION_LEVEL);
|
||||||
|
#else
|
||||||
|
return COMMAND_PERMISSION_CHECK.check(source.permissions());
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
builder.then(new ConfigCommand().buildCommand());
|
builder.then(new ConfigCommand().buildCommand());
|
||||||
builder.then(new DebugCommand().buildCommand());
|
builder.then(new DebugCommand().buildCommand());
|
||||||
@@ -43,7 +78,7 @@ public class CommandInitializer
|
|||||||
builder.then(new CrashCommand().buildCommand());
|
builder.then(new CrashCommand().buildCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.commandDispatcher.register(builder);
|
commandDispatcher.register(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package com.seibel.distanthorizons.common.commands;
|
|||||||
import com.mojang.brigadier.arguments.*;
|
import com.mojang.brigadier.arguments.*;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
import com.seibel.distanthorizons.core.config.types.AbstractConfigType;
|
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
|
||||||
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ public class ConfigCommand extends AbstractCommand
|
|||||||
LiteralArgumentBuilder<CommandSourceStack> builder = literal("config");
|
LiteralArgumentBuilder<CommandSourceStack> builder = literal("config");
|
||||||
HashSet<String> addedCommands = new HashSet<>();
|
HashSet<String> addedCommands = new HashSet<>();
|
||||||
|
|
||||||
for (AbstractConfigType<?, ?> type : ConfigBase.INSTANCE.entries)
|
for (AbstractConfigBase<?> type : ConfigHandler.INSTANCE.configBaseList)
|
||||||
{
|
{
|
||||||
// Skip non-config entries
|
// Skip non-config entries
|
||||||
if (!(type instanceof ConfigEntry))
|
if (!(type instanceof ConfigEntry))
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ public class CrashCommand extends AbstractCommand
|
|||||||
.requires(this::isPlayerSource)
|
.requires(this::isPlayerSource)
|
||||||
.then(literal("encode")
|
.then(literal("encode")
|
||||||
.executes(c -> {
|
.executes(c -> {
|
||||||
assert SharedApi.getIDhServerWorld() != null;
|
assert SharedApi.tryGetDhServerWorld() != null;
|
||||||
|
|
||||||
ServerPlayerState serverPlayerState = SharedApi.getIDhServerWorld().getServerPlayerStateManager()
|
ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld().getServerPlayerStateManager()
|
||||||
.getConnectedPlayer(this.getSourcePlayer(c));
|
.getConnectedPlayer(this.getSourcePlayer(c));
|
||||||
if (serverPlayerState != null)
|
if (serverPlayerState != null)
|
||||||
{
|
{
|
||||||
@@ -29,9 +29,9 @@ public class CrashCommand extends AbstractCommand
|
|||||||
}))
|
}))
|
||||||
.then(literal("decode")
|
.then(literal("decode")
|
||||||
.executes(c -> {
|
.executes(c -> {
|
||||||
assert SharedApi.getIDhServerWorld() != null;
|
assert SharedApi.tryGetDhServerWorld() != null;
|
||||||
|
|
||||||
ServerPlayerState serverPlayerState = SharedApi.getIDhServerWorld().getServerPlayerStateManager()
|
ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld().getServerPlayerStateManager()
|
||||||
.getConnectedPlayer(this.getSourcePlayer(c));
|
.getConnectedPlayer(this.getSourcePlayer(c));
|
||||||
if (serverPlayerState != null)
|
if (serverPlayerState != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ public class DependencySetup
|
|||||||
SingletonInjector.INSTANCE.bind(IVersionConstants.class, VersionConstants.INSTANCE);
|
SingletonInjector.INSTANCE.bind(IVersionConstants.class, VersionConstants.INSTANCE);
|
||||||
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
||||||
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
|
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
|
||||||
DependencySetupDoneCheck.isDone = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createServerBindings()
|
public static void createServerBindings()
|
||||||
|
|||||||
@@ -79,8 +79,12 @@ public class VersionConstants implements IVersionConstants
|
|||||||
#elif MC_VER == MC_1_21_8
|
#elif MC_VER == MC_1_21_8
|
||||||
return "1.21.8";
|
return "1.21.8";
|
||||||
|
|
||||||
|
#elif MC_VER == MC_1_21_9
|
||||||
|
return "1.21.9";
|
||||||
#elif MC_VER == MC_1_21_10
|
#elif MC_VER == MC_1_21_10
|
||||||
return "1.21.10";
|
return "1.21.10";
|
||||||
|
#elif MC_VER == MC_1_21_11
|
||||||
|
return "1.21.11";
|
||||||
#else
|
#else
|
||||||
ERROR MC version constant missing
|
ERROR MC version constant missing
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvironmentWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.IBatchGeneratorEnvironmentWrapper;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
#if MC_VER > MC_1_17_1
|
#if MC_VER > MC_1_17_1
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
@@ -67,7 +67,7 @@ public class WrapperFactory implements IWrapperFactory
|
|||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractBatchGenerationEnvironmentWrapper createBatchGenerator(IDhLevel targetLevel)
|
public IBatchGeneratorEnvironmentWrapper createBatchGenerator(IDhLevel targetLevel)
|
||||||
{
|
{
|
||||||
if (targetLevel instanceof IDhServerLevel)
|
if (targetLevel instanceof IDhServerLevel)
|
||||||
{
|
{
|
||||||
|
|||||||
+217
-15
@@ -1,16 +1,31 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.BlockBiomeWrapperPair;
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.ColorResolver;
|
import net.minecraft.world.level.ColorResolver;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
#endif
|
#endif
|
||||||
@@ -18,10 +33,24 @@ import net.minecraft.core.Holder;
|
|||||||
|
|
||||||
public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
||||||
{
|
{
|
||||||
protected final BiomeWrapper biomeWrapper;
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
protected final int smoothingRadiusInBlocks;
|
#if MC_VER < MC_1_18_2
|
||||||
protected final FullDataSourceV2 fullDataSource;
|
private static final ConcurrentHashMap<String, Biome> BIOME_BY_RESOURCE_STRING = new ConcurrentHashMap<>();
|
||||||
|
#else
|
||||||
|
private static final ConcurrentHashMap<String, Holder<Biome>> BIOME_BY_RESOURCE_STRING = new ConcurrentHashMap<>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private static final ConcurrentHashMap<BlockBiomeWrapperPair, Integer> COLOR_BY_BLOCK_BIOME_PAIR = new ConcurrentHashMap<>();
|
||||||
|
/** returned if the color cache is incomplete */
|
||||||
|
public static final int INVALID_COLOR = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
protected BiomeWrapper biomeWrapper;
|
||||||
|
protected BlockStateWrapper blockStateWrapper;
|
||||||
|
protected FullDataSourceV2 fullDataSource;
|
||||||
|
protected int smoothingRadiusInBlocks;
|
||||||
|
protected IClientLevelWrapper clientLevelWrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -29,10 +58,18 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public AbstractDhTintGetter(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource)
|
public AbstractDhTintGetter() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutates this getter so we can access the necessary
|
||||||
|
* variables for tint getting.
|
||||||
|
*/
|
||||||
|
public void update(BiomeWrapper biomeWrapper, BlockStateWrapper blockStateWrapper, FullDataSourceV2 fullDataSource, IClientLevelWrapper clientLevelWrapper)
|
||||||
{
|
{
|
||||||
this.biomeWrapper = biomeWrapper;
|
this.biomeWrapper = biomeWrapper;
|
||||||
|
this.blockStateWrapper = blockStateWrapper;
|
||||||
this.fullDataSource = fullDataSource;
|
this.fullDataSource = fullDataSource;
|
||||||
|
this.clientLevelWrapper = clientLevelWrapper;
|
||||||
this.smoothingRadiusInBlocks = Config.Client.Advanced.Graphics.Quality.lodBiomeBlending.get();
|
this.smoothingRadiusInBlocks = Config.Client.Advanced.Graphics.Quality.lodBiomeBlending.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +79,27 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
// shared methods //
|
// shared methods //
|
||||||
//================//
|
//================//
|
||||||
|
|
||||||
|
/** Called by MC's tint getter */
|
||||||
@Override
|
@Override
|
||||||
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
|
||||||
|
{
|
||||||
|
DhBlockPosMutable mutableBlockPos = new DhBlockPosMutable(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||||
|
return this.tryGetBlockTint(mutableBlockPos, colorResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public int tryGetBlockTint(DhBlockPosMutable mutableBlockPos)
|
||||||
|
{ return this.tryGetBlockTint(mutableBlockPos, null); }
|
||||||
|
|
||||||
|
private int tryGetBlockTint(DhBlockPosMutable mutableBlockPos, @Nullable ColorResolver colorResolver)
|
||||||
{
|
{
|
||||||
// determine how wide this data source is so we can determine
|
// determine how wide this data source is so we can determine
|
||||||
// if blending should be used
|
// if blending should be used
|
||||||
@@ -57,7 +113,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
if (this.smoothingRadiusInBlocks == 0
|
if (this.smoothingRadiusInBlocks == 0
|
||||||
|| dataSourceLodWidthInBlocks > this.smoothingRadiusInBlocks)
|
|| dataSourceLodWidthInBlocks > this.smoothingRadiusInBlocks)
|
||||||
{
|
{
|
||||||
return colorResolver.getColor(this.unwrapBiome(this.biomeWrapper.biome), blockPos.getX(), blockPos.getZ());
|
return this.tryGetClientBiomeColor(colorResolver, this.biomeWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -67,13 +123,14 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
int rollingGreen = 0;
|
int rollingGreen = 0;
|
||||||
int rollingBlue = 0;
|
int rollingBlue = 0;
|
||||||
|
|
||||||
int xMin = blockPos.getX() - this.smoothingRadiusInBlocks;
|
int xMin = mutableBlockPos.getX() - this.smoothingRadiusInBlocks;
|
||||||
int xMax = blockPos.getX() + this.smoothingRadiusInBlocks;
|
int xMax = mutableBlockPos.getX() + this.smoothingRadiusInBlocks + 1; // +1 to account for the center block
|
||||||
|
|
||||||
int zMin = blockPos.getZ() - this.smoothingRadiusInBlocks;
|
int zMin = mutableBlockPos.getZ() - this.smoothingRadiusInBlocks;
|
||||||
int zMax = blockPos.getZ() + this.smoothingRadiusInBlocks;
|
int zMax = mutableBlockPos.getZ() + this.smoothingRadiusInBlocks + 1;
|
||||||
|
|
||||||
|
int levelMinY = this.clientLevelWrapper.getMinHeight();
|
||||||
|
|
||||||
DhBlockPosMutable mutableBlockPos = new DhBlockPosMutable(0, blockPos.getY(), 0);
|
|
||||||
for (int x = xMin; x < xMax; x++)
|
for (int x = xMin; x < xMax; x++)
|
||||||
{
|
{
|
||||||
for (int z = zMin; z < zMax; z++)
|
for (int z = zMin; z < zMax; z++)
|
||||||
@@ -84,16 +141,21 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
// this can return the same position/datapoint for larger LODs duplicating work,
|
// this can return the same position/datapoint for larger LODs duplicating work,
|
||||||
// however for small smoothing ranges that isn't a big deal and for large LODs
|
// however for small smoothing ranges that isn't a big deal and for large LODs
|
||||||
// we ignore smoothing anyway
|
// we ignore smoothing anyway
|
||||||
long dataPoint = this.fullDataSource.getAtBlockPos(mutableBlockPos);
|
long dataPoint = this.fullDataSource.getDataPointAtBlockPos(mutableBlockPos.getX(), mutableBlockPos.getY(), mutableBlockPos.getZ(), levelMinY);
|
||||||
if (dataPoint == FullDataPointUtil.EMPTY_DATA_POINT)
|
if (dataPoint == FullDataPointUtil.EMPTY_DATA_POINT)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// get the color for this nearby position
|
// get the color for this nearby position
|
||||||
int id = FullDataPointUtil.getId(dataPoint);
|
int id = FullDataPointUtil.getId(dataPoint);
|
||||||
BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id);
|
BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id);
|
||||||
int color = colorResolver.getColor(this.unwrapBiome(biomeWrapper.biome), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
int color = this.tryGetClientBiomeColor(colorResolver, biomeWrapper);
|
||||||
|
if (color == INVALID_COLOR)
|
||||||
|
{
|
||||||
|
return INVALID_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// rolling average
|
// rolling average
|
||||||
@@ -110,7 +172,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
// just use the default center's color
|
// just use the default center's color
|
||||||
if (dataPointCount == 0)
|
if (dataPointCount == 0)
|
||||||
{
|
{
|
||||||
return colorResolver.getColor(this.unwrapBiome(this.biomeWrapper.biome), blockPos.getX(), blockPos.getZ());
|
return this.tryGetClientBiomeColor(colorResolver, this.biomeWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
int colorInt = ColorUtil.argbToInt(
|
int colorInt = ColorUtil.argbToInt(
|
||||||
@@ -121,7 +183,50 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
return colorInt;
|
return colorInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Biome unwrapBiome(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
/**
|
||||||
|
* If given a ColorResolver this will always succeed. <Br>
|
||||||
|
* If not it will attempt to use the cached color.
|
||||||
|
*/
|
||||||
|
private int tryGetClientBiomeColor(@Nullable ColorResolver colorResolver, BiomeWrapper biomeWrapper)
|
||||||
|
{
|
||||||
|
BlockBiomeWrapperPair pair = BlockBiomeWrapperPair.get(this.blockStateWrapper, biomeWrapper);
|
||||||
|
|
||||||
|
// use the cached color if possible
|
||||||
|
Integer cachedColor = COLOR_BY_BLOCK_BIOME_PAIR.get(pair); // explicit Integer return here reduces unnecessary allocations
|
||||||
|
if (cachedColor != null)
|
||||||
|
{
|
||||||
|
return cachedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorResolver == null)
|
||||||
|
{
|
||||||
|
// no color resolver is present,
|
||||||
|
// the cache needs to be populated before
|
||||||
|
// we can use the fast path
|
||||||
|
return INVALID_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int color = colorResolver.getColor(unwrapClientBiome(biomeWrapper), 0, 0);
|
||||||
|
COLOR_BY_BLOCK_BIOME_PAIR.put(pair, color);
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Biome unwrapClientBiome(BiomeWrapper biomeWrapper)
|
||||||
|
{
|
||||||
|
String biomeString = biomeWrapper.getSerialString();
|
||||||
|
if (biomeString == null
|
||||||
|
|| biomeString.isEmpty()
|
||||||
|
|| biomeString.equals(BiomeWrapper.EMPTY_BIOME_STRING))
|
||||||
|
{
|
||||||
|
// default to "plains" for empty/invalid biomes
|
||||||
|
biomeString = "minecraft:plains";
|
||||||
|
}
|
||||||
|
|
||||||
|
return unwrapBiome(getClientBiome(biomeString));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Biome unwrapBiome(#if MC_VER >= MC_1_18_2 Holder<Biome> #else Biome #endif biome)
|
||||||
{
|
{
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
return biome.value();
|
return biome.value();
|
||||||
@@ -130,6 +235,103 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Previously, this class might have immediately unwrapped the Holder like this:</p>
|
||||||
|
* <pre>{@code
|
||||||
|
* // Inside constructor (OLD WAY - PROBLEMATIC):
|
||||||
|
* Holder<Biome> biomeHolder = getTheHolderFromSomewhere();
|
||||||
|
* this.biome = biomeHolder.value(); // <-- PROBLEM HERE
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <p>This approach is problematic because the {@link net.minecraft.core.Holder} system,
|
||||||
|
* particularly {@code Holder.Reference}, is designed for <strong>late binding</strong>. Here's why storing
|
||||||
|
* the Holder itself is now necessary:</p>
|
||||||
|
* <ol>
|
||||||
|
* <li>A {@code Holder.Reference<Biome>} might be created initially just with a
|
||||||
|
* {@link net.minecraft.resources.ResourceKey} (like {@code minecraft:plains}), but its actual
|
||||||
|
* {@link net.minecraft.core.Holder#value() value()} (the {@code Biome} object itself) might be {@code null}
|
||||||
|
* at construction time.</li>
|
||||||
|
* <li>Later, during game loading, registry population, or potentially due to modifications by other mods
|
||||||
|
* (e.g., Polytone), the system calls internal binding methods (like {@code bindValue(Biome)})
|
||||||
|
* on the {@code Holder} instance. This sets or <strong>updates</strong> the internal reference to the
|
||||||
|
* actual {@code Biome} object.</li>
|
||||||
|
* <li>Crucially, the binding process might assign a completely <strong>new</strong> {@code Biome} object
|
||||||
|
* instance to the {@code Holder} reference, replacing any previous one.</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* <p>If we unwrapped the {@code Holder} using {@code .value()} within the constructor (the old way),
|
||||||
|
* our class's internal {@code biome} field would permanently store a reference to whatever {@code Biome}
|
||||||
|
* object the {@code Holder} pointed to *at that exact moment*. It would have no link back to the
|
||||||
|
* {@code Holder} and would be unaware if the {@code Holder} was later updated to point to a different
|
||||||
|
* (or the initially missing) {@code Biome} object. This would lead to using stale or even {@code null} data.</p>
|
||||||
|
*
|
||||||
|
* <p>By storing the {@code Holder<Biome>} itself, this class can call {@link net.minecraft.core.Holder#value()}
|
||||||
|
* whenever the biome information is needed, ensuring it always retrieves the most current {@code Biome}
|
||||||
|
* instance associated with the holder at that time.</p>
|
||||||
|
*/
|
||||||
|
private static #if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif getClientBiome(String biomeResourceString)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
Biome biome;
|
||||||
|
#else
|
||||||
|
Holder<Biome> biome;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// calling get instead of compute is slightly faster for already
|
||||||
|
// computed values
|
||||||
|
biome = BIOME_BY_RESOURCE_STRING.get(biomeResourceString);
|
||||||
|
if (biome != null)
|
||||||
|
{
|
||||||
|
return biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// cache the client biomes so we don't have to re-parse the resource location every time
|
||||||
|
return BIOME_BY_RESOURCE_STRING.compute(biomeResourceString,
|
||||||
|
(resourceString, existingBiome) ->
|
||||||
|
{
|
||||||
|
if (existingBiome != null)
|
||||||
|
{
|
||||||
|
return existingBiome;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientLevel clientLevel = Minecraft.getInstance().level;
|
||||||
|
if (clientLevel == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
throw new IllegalStateException("Attempted to get client biome when no client level was loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
BiomeWrapper.BiomeDeserializeResult result;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = BiomeWrapper.deserializeBiome(resourceString, clientLevel.registryAccess());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to deserialize client biome ["+resourceString+"], using fallback...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = BiomeWrapper.deserializeBiome(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, clientLevel.registryAccess());
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
// should never happen, if it does this log will explode, but just in case
|
||||||
|
LOGGER.error("Unable to deserialize fallback client biome ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], returning NULL.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.success)
|
||||||
|
{
|
||||||
|
existingBiome = result.biome;
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingBiome;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-9
@@ -26,10 +26,10 @@ import java.util.Optional;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
|
|
||||||
@@ -45,7 +45,12 @@ import net.minecraft.core.Holder;
|
|||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
@@ -57,7 +62,7 @@ import net.minecraft.world.level.biome.Biomes;
|
|||||||
public class BiomeWrapper implements IBiomeWrapper
|
public class BiomeWrapper implements IBiomeWrapper
|
||||||
{
|
{
|
||||||
// must be defined before AIR, otherwise a null pointer will be thrown
|
// must be defined before AIR, otherwise a null pointer will be thrown
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
@@ -103,7 +108,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
// constructors //
|
// constructors //
|
||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
static public IBiomeWrapper getBiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
|
public static BiomeWrapper getBiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
|
||||||
{
|
{
|
||||||
if (biome == null)
|
if (biome == null)
|
||||||
{
|
{
|
||||||
@@ -111,9 +116,10 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (WRAPPER_BY_BIOME.containsKey(biome))
|
BiomeWrapper biomeWrapper = WRAPPER_BY_BIOME.get(biome);
|
||||||
|
if (biomeWrapper != null)
|
||||||
{
|
{
|
||||||
return WRAPPER_BY_BIOME.get(biome);
|
return biomeWrapper;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -215,7 +221,12 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
Level level = (Level)levelWrapper.getWrappedMcObject();
|
Level level = (Level)levelWrapper.getWrappedMcObject();
|
||||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_11
|
||||||
ResourceLocation resourceLocation;
|
ResourceLocation resourceLocation;
|
||||||
|
#else
|
||||||
|
Identifier resourceLocation;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
|
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
|
||||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||||
@@ -299,7 +310,7 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
foundWrapper = (BiomeWrapper) getBiomeWrapper(deserializeResult.biome, levelWrapper);
|
foundWrapper = getBiomeWrapper(deserializeResult.biome, levelWrapper);
|
||||||
return foundWrapper;
|
return foundWrapper;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -322,13 +333,19 @@ public class BiomeWrapper implements IBiomeWrapper
|
|||||||
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_11
|
||||||
ResourceLocation resourceLocation;
|
ResourceLocation resourceLocation;
|
||||||
|
#else
|
||||||
|
Identifier resourceLocation;
|
||||||
|
#endif
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER <= MC_1_20_6
|
||||||
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||||
|
#else
|
||||||
|
resourceLocation = Identifier.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
+32
-10
@@ -28,14 +28,13 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.world.level.block.BeaconBeamBlock;
|
import net.minecraft.world.level.block.BeaconBeamBlock;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.SoundType;
|
import net.minecraft.world.level.block.SoundType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -63,6 +62,12 @@ import net.minecraft.world.level.EmptyBlockGetter;
|
|||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
public class BlockStateWrapper implements IBlockStateWrapper
|
public class BlockStateWrapper implements IBlockStateWrapper
|
||||||
{
|
{
|
||||||
/** example "minecraft:water" */
|
/** example "minecraft:water" */
|
||||||
@@ -72,7 +77,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|
|
||||||
|
|
||||||
// must be defined before AIR, otherwise a null pointer will be thrown
|
// must be defined before AIR, otherwise a null pointer will be thrown
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>();
|
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>();
|
||||||
public static final ConcurrentHashMap<String, BlockStateWrapper> WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>();
|
public static final ConcurrentHashMap<String, BlockStateWrapper> WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>();
|
||||||
@@ -87,7 +92,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null;
|
public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null;
|
||||||
|
|
||||||
/** keep track of broken blocks so we don't log every time */
|
/** keep track of broken blocks so we don't log every time */
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
private static final HashSet<ResourceLocation> BROKEN_RESOURCE_LOCATIONS = new HashSet<>();
|
private static final HashSet<ResourceLocation> BROKEN_RESOURCE_LOCATIONS = new HashSet<>();
|
||||||
|
#else
|
||||||
|
private static final HashSet<Identifier> BROKEN_RESOURCE_LOCATIONS = new HashSet<>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -274,7 +283,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|
|
||||||
HashSet<String> baseIgnoredBlock = new HashSet<>();
|
HashSet<String> baseIgnoredBlock = new HashSet<>();
|
||||||
baseIgnoredBlock.add(AIR_STRING);
|
baseIgnoredBlock.add(AIR_STRING);
|
||||||
rendererIgnoredBlocks = getBlockWrappers(Config.Client.Advanced.Graphics.Culling.ignoredRenderBlockCsv, baseIgnoredBlock, levelWrapper);
|
rendererIgnoredBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.ignoredRenderBlockCsv, baseIgnoredBlock, levelWrapper);
|
||||||
return rendererIgnoredBlocks;
|
return rendererIgnoredBlocks;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -291,7 +300,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|
|
||||||
HashSet<String> baseIgnoredBlock = new HashSet<>();
|
HashSet<String> baseIgnoredBlock = new HashSet<>();
|
||||||
baseIgnoredBlock.add(AIR_STRING);
|
baseIgnoredBlock.add(AIR_STRING);
|
||||||
rendererIgnoredCaveBlocks = getBlockWrappers(Config.Client.Advanced.Graphics.Culling.ignoredRenderCaveBlockCsv, baseIgnoredBlock, levelWrapper);
|
rendererIgnoredCaveBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.ignoredRenderCaveBlockCsv, baseIgnoredBlock, levelWrapper);
|
||||||
return rendererIgnoredCaveBlocks;
|
return rendererIgnoredCaveBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +311,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
|
|
||||||
// lod builder helpers //
|
// lod builder helpers //
|
||||||
|
|
||||||
private static HashSet<IBlockStateWrapper> getBlockWrappers(ConfigEntry<String> config, HashSet<String> baseResourceLocations, ILevelWrapper levelWrapper)
|
private static HashSet<IBlockStateWrapper> getAllBlockWrappers(ConfigEntry<String> config, HashSet<String> baseResourceLocations, ILevelWrapper levelWrapper)
|
||||||
{
|
{
|
||||||
// get the base blocks
|
// get the base blocks
|
||||||
HashSet<String> blockStringList = new HashSet<>();
|
HashSet<String> blockStringList = new HashSet<>();
|
||||||
@@ -318,9 +327,9 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
blockStringList.addAll(Arrays.asList(ignoreBlockCsv.split(",")));
|
blockStringList.addAll(Arrays.asList(ignoreBlockCsv.split(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBlockWrappers(blockStringList, levelWrapper);
|
return getAllBlockWrappers(blockStringList, levelWrapper);
|
||||||
}
|
}
|
||||||
private static HashSet<IBlockStateWrapper> getBlockWrappers(HashSet<String> blockResourceLocationSet, ILevelWrapper levelWrapper)
|
private static HashSet<IBlockStateWrapper> getAllBlockWrappers(HashSet<String> blockResourceLocationSet, ILevelWrapper levelWrapper)
|
||||||
{
|
{
|
||||||
// deserialize each of the given resource locations
|
// deserialize each of the given resource locations
|
||||||
HashSet<IBlockStateWrapper> blockStateWrappers = new HashSet<>();
|
HashSet<IBlockStateWrapper> blockStateWrappers = new HashSet<>();
|
||||||
@@ -555,7 +564,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_11
|
||||||
ResourceLocation resourceLocation;
|
ResourceLocation resourceLocation;
|
||||||
|
#else
|
||||||
|
Identifier resourceLocation;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
resourceLocation = Registry.BLOCK.getKey(this.blockState.getBlock());
|
resourceLocation = Registry.BLOCK.getKey(this.blockState.getBlock());
|
||||||
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
|
||||||
@@ -587,7 +601,8 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
// we need the final string for the concurrent hash map later
|
// we need the final string for the concurrent hash map later
|
||||||
final String finalResourceStateString = resourceStateString;
|
final String finalResourceStateString = resourceStateString;
|
||||||
|
|
||||||
if (finalResourceStateString.equals(AIR_STRING) || finalResourceStateString.equals("")) // the empty string shouldn't normally happen, but just in case
|
if (finalResourceStateString.equals(AIR_STRING)
|
||||||
|
|| finalResourceStateString.equals("")) // the empty string shouldn't normally happen, but just in case
|
||||||
{
|
{
|
||||||
return AIR;
|
return AIR;
|
||||||
}
|
}
|
||||||
@@ -621,13 +636,20 @@ public class BlockStateWrapper implements IBlockStateWrapper
|
|||||||
throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "].");
|
throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_11
|
||||||
ResourceLocation resourceLocation;
|
ResourceLocation resourceLocation;
|
||||||
|
#else
|
||||||
|
Identifier resourceLocation;
|
||||||
|
#endif
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER < MC_1_21_1
|
||||||
resourceLocation = new ResourceLocation(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
resourceLocation = new ResourceLocation(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
||||||
|
#else
|
||||||
|
resourceLocation = Identifier.fromNamespaceAndPath(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
+56
-51
@@ -20,17 +20,16 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.LevelReader;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.FlowerBlock;
|
import net.minecraft.world.level.block.FlowerBlock;
|
||||||
import net.minecraft.world.level.block.LeavesBlock;
|
import net.minecraft.world.level.block.LeavesBlock;
|
||||||
@@ -41,7 +40,7 @@ import net.minecraft.util.RandomSource;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -63,10 +62,8 @@ import net.minecraft.client.renderer.block.model.BlockModelPart;
|
|||||||
*/
|
*/
|
||||||
public class ClientBlockStateColorCache
|
public class ClientBlockStateColorCache
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
// TODO it isn't that we need the level, but that we need the adjacent data
|
|
||||||
// maybe we can pass in the full data source?
|
|
||||||
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
|
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
|
||||||
private static final HashSet<BlockState> BROKEN_BLOCK_STATES = new HashSet<>();
|
private static final HashSet<BlockState> BROKEN_BLOCK_STATES = new HashSet<>();
|
||||||
|
|
||||||
@@ -96,14 +93,11 @@ public class ClientBlockStateColorCache
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private final IClientLevelWrapper clientLevelWrapper;
|
private final IClientLevelWrapper clientLevelWrapper;
|
||||||
private final BlockStateWrapper blockStateWrapper;
|
|
||||||
|
|
||||||
private final BlockState blockState;
|
private final BlockState blockState;
|
||||||
private final LevelReader level;
|
private final BlockStateWrapper blockStateWrapper;
|
||||||
|
|
||||||
private boolean isColorResolved = false;
|
private boolean isColorResolved = false;
|
||||||
private int baseColor = 0;
|
private int baseColor = 0;
|
||||||
private boolean needShade = true;
|
|
||||||
private boolean needPostTinting = false;
|
private boolean needPostTinting = false;
|
||||||
private int tintIndex = 0;
|
private int tintIndex = 0;
|
||||||
|
|
||||||
@@ -171,18 +165,20 @@ public class ClientBlockStateColorCache
|
|||||||
0.93011117f, 0.9386859f, 0.9473069f, 0.9559735f, 0.9646866f, 0.9734455f, 0.98225087f, 0.9911022f, 1.0f
|
0.93011117f, 0.9386859f, 0.9473069f, 0.9559735f, 0.9646866f, 0.9734455f, 0.98225087f, 0.9911022f, 1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final ThreadLocal<TintWithoutLevelOverrider> TintWithoutLevelOverrideGetter = ThreadLocal.withInitial(() -> new TintWithoutLevelOverrider());
|
||||||
|
private static final ThreadLocal<TintGetterOverride> TintOverrideGetter = ThreadLocal.withInitial(() -> new TintGetterOverride());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
//=============//
|
||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper samplingLevel)
|
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper clientLevelWrapper)
|
||||||
{
|
{
|
||||||
this.blockState = blockState;
|
this.blockState = blockState;
|
||||||
this.clientLevelWrapper = samplingLevel;
|
this.blockStateWrapper = BlockStateWrapper.fromBlockState(blockState, clientLevelWrapper);
|
||||||
this.level = (LevelReader) samplingLevel.getWrappedMcObject();
|
this.clientLevelWrapper = clientLevelWrapper;
|
||||||
this.blockStateWrapper = BlockStateWrapper.fromBlockState(this.blockState, this.clientLevelWrapper);
|
|
||||||
|
|
||||||
this.resolveColors();
|
this.resolveColors();
|
||||||
}
|
}
|
||||||
@@ -236,32 +232,29 @@ public class ClientBlockStateColorCache
|
|||||||
|
|
||||||
this.needPostTinting = firstQuad.isTinted();
|
this.needPostTinting = firstQuad.isTinted();
|
||||||
#if MC_VER <= MC_1_21_4
|
#if MC_VER <= MC_1_21_4
|
||||||
this.needShade = firstQuad.isShade();
|
|
||||||
this.tintIndex = firstQuad.getTintIndex();
|
this.tintIndex = firstQuad.getTintIndex();
|
||||||
#else
|
#else
|
||||||
this.needShade = firstQuad.shade();
|
|
||||||
this.tintIndex = firstQuad.tintIndex();
|
this.tintIndex = firstQuad.tintIndex();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
this.baseColor = calculateColorFromTexture(
|
this.baseColor = calculateColorFromTexture(
|
||||||
firstQuad.sprite,
|
firstQuad.sprite,
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
#elif MC_VER < MC_1_21_5
|
#elif MC_VER < MC_1_21_5
|
||||||
this.baseColor = calculateColorFromTexture(
|
this.baseColor = calculateColorFromTexture(
|
||||||
firstQuad.getSprite(),
|
firstQuad.getSprite(),
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
#else
|
#else
|
||||||
this.baseColor = calculateColorFromTexture(
|
this.baseColor = calculateColorFromTexture(
|
||||||
firstQuad.sprite(),
|
firstQuad.sprite(),
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Backup method.
|
// Backup method.
|
||||||
this.needPostTinting = false;
|
this.needPostTinting = false;
|
||||||
this.needShade = false;
|
|
||||||
this.tintIndex = 0;
|
this.tintIndex = 0;
|
||||||
this.baseColor = this.getParticleIconColor();
|
this.baseColor = this.getParticleIconColor();
|
||||||
}
|
}
|
||||||
@@ -270,19 +263,11 @@ public class ClientBlockStateColorCache
|
|||||||
{
|
{
|
||||||
// Liquid Block
|
// Liquid Block
|
||||||
this.needPostTinting = true;
|
this.needPostTinting = true;
|
||||||
this.needShade = false;
|
|
||||||
this.tintIndex = 0;
|
this.tintIndex = 0;
|
||||||
this.baseColor = this.getParticleIconColor();
|
this.baseColor = this.getParticleIconColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//String serialString = this.blockStateWrapper.getSerialString();
|
|
||||||
//if (serialString.contains("minecraft:water")
|
|
||||||
// || serialString.contains("grass"))
|
|
||||||
//{
|
|
||||||
// BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
|
|
||||||
//}
|
|
||||||
|
|
||||||
this.isColorResolved = true;
|
this.isColorResolved = true;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -320,7 +305,7 @@ public class ClientBlockStateColorCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Perhaps make this not just use the first frame?
|
//TODO: Perhaps make this not just use the first frame?
|
||||||
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
|
private static int calculateColorFromTexture(TextureAtlasSprite texture, EColorMode colorMode)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int alpha = 0;
|
int alpha = 0;
|
||||||
@@ -330,8 +315,8 @@ public class ClientBlockStateColorCache
|
|||||||
int tempColor;
|
int tempColor;
|
||||||
|
|
||||||
// don't render Chiseled blocks.
|
// don't render Chiseled blocks.
|
||||||
// Since ColorMode is set per block, you only need to check this once.
|
// Since EColorMode is set per block, you only need to check this once.
|
||||||
if (colorMode != ColorMode.Chisel)
|
if (colorMode != EColorMode.Chisel)
|
||||||
{
|
{
|
||||||
// textures normally use u and v instead of x and y
|
// textures normally use u and v instead of x and y
|
||||||
for (int v = 0; v < getTextureHeight(texture); v++)
|
for (int v = 0; v < getTextureHeight(texture); v++)
|
||||||
@@ -349,7 +334,7 @@ public class ClientBlockStateColorCache
|
|||||||
int b = (tempColor & 0x00FF0000) >>> 16;
|
int b = (tempColor & 0x00FF0000) >>> 16;
|
||||||
int a = (tempColor & 0xFF000000) >>> 24;
|
int a = (tempColor & 0xFF000000) >>> 24;
|
||||||
int scale = 1;
|
int scale = 1;
|
||||||
if (colorMode == ColorMode.Leaves)
|
if (colorMode == EColorMode.Leaves)
|
||||||
{
|
{
|
||||||
//switch (//FIXME add config option)
|
//switch (//FIXME add config option)
|
||||||
// case BLACK:
|
// case BLACK:
|
||||||
@@ -368,11 +353,11 @@ public class ClientBlockStateColorCache
|
|||||||
// break; //do nothing, let it count towards transparency
|
// break; //do nothing, let it count towards transparency
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (a == 0 && colorMode != ColorMode.Glass)
|
else if (a == 0 && colorMode != EColorMode.Glass)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (colorMode == ColorMode.Flower && (g + 25 < b || g + 25 < r))
|
else if (colorMode == EColorMode.Flower && (g + 25 < b || g + 25 < r))
|
||||||
{
|
{
|
||||||
scale = FLOWER_COLOR_SCALE;
|
scale = FLOWER_COLOR_SCALE;
|
||||||
}
|
}
|
||||||
@@ -455,7 +440,7 @@ public class ClientBlockStateColorCache
|
|||||||
{
|
{
|
||||||
return calculateColorFromTexture(
|
return calculateColorFromTexture(
|
||||||
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
|
||||||
ColorMode.getColorMode(this.blockState.getBlock()));
|
EColorMode.getColorMode(this.blockState.getBlock()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -464,7 +449,7 @@ public class ClientBlockStateColorCache
|
|||||||
// public getter //
|
// public getter //
|
||||||
//===============//
|
//===============//
|
||||||
|
|
||||||
public int getColor(BiomeWrapper biome, FullDataSourceV2 fullDataSource, DhBlockPos pos)
|
public int getColor(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource, DhBlockPos blockPos)
|
||||||
{
|
{
|
||||||
// only get the tint if the block needs to be tinted
|
// only get the tint if the block needs to be tinted
|
||||||
if (!this.needPostTinting)
|
if (!this.needPostTinting)
|
||||||
@@ -488,16 +473,27 @@ public class ClientBlockStateColorCache
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tintColor = Minecraft.getInstance().getBlockColors()
|
TintWithoutLevelOverrider tintOverride = TintWithoutLevelOverrideGetter.get();
|
||||||
.getColor(this.blockState,
|
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
|
||||||
new TintWithoutLevelSmoothOverrider(biome, fullDataSource), // TODO can this object be cached?
|
|
||||||
McObjectConverter.Convert(pos),
|
// try using DH's cached tint values first if possible
|
||||||
this.tintIndex);
|
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
|
||||||
|
if (tintColor == AbstractDhTintGetter.INVALID_COLOR)
|
||||||
|
{
|
||||||
|
// one or more tint values weren't calculated,
|
||||||
|
// we need MC's color resolver
|
||||||
|
tintColor = Minecraft.getInstance()
|
||||||
|
.getBlockColors()
|
||||||
|
.getColor(this.blockState,
|
||||||
|
tintOverride,
|
||||||
|
McObjectConverter.Convert(blockPos),
|
||||||
|
this.tintIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (UnsupportedOperationException e)
|
catch (UnsupportedOperationException e)
|
||||||
{
|
{
|
||||||
// this exception generally occurs if the tint requires other blocks besides itself
|
// this exception generally occurs if the tint requires other blocks besides itself
|
||||||
LOGGER.debug("Unable to use ["+TintWithoutLevelSmoothOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biome + "] at pos: " + pos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e);
|
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);
|
BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -505,13 +501,22 @@ public class ClientBlockStateColorCache
|
|||||||
// use the level logic only if requested
|
// use the level logic only if requested
|
||||||
if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
|
if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
|
||||||
{
|
{
|
||||||
// this logic can't be used all the time due to it breaking some blocks tinting
|
// the level shouldn't be used all the time due to it breaking some blocks tinting
|
||||||
// specifically oceans don't render correctly
|
// specifically oceans don't render correctly
|
||||||
tintColor = Minecraft.getInstance().getBlockColors()
|
|
||||||
.getColor(this.blockState,
|
TintGetterOverride tintOverride = TintOverrideGetter.get();
|
||||||
new TintGetterOverrideSmooth(this.level, biome, fullDataSource), // TODO can this object be cached?
|
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
|
||||||
McObjectConverter.Convert(pos),
|
|
||||||
this.tintIndex);
|
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
|
||||||
|
if (tintColor == AbstractDhTintGetter.INVALID_COLOR)
|
||||||
|
{
|
||||||
|
tintColor = Minecraft.getInstance()
|
||||||
|
.getBlockColors()
|
||||||
|
.getColor(this.blockState,
|
||||||
|
tintOverride,
|
||||||
|
McObjectConverter.Convert(blockPos),
|
||||||
|
this.tintIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -519,7 +524,7 @@ public class ClientBlockStateColorCache
|
|||||||
// only display the error once per block/biome type to reduce log spam
|
// only display the error once per block/biome type to reduce log spam
|
||||||
if (!BROKEN_BLOCK_STATES.contains(this.blockState))
|
if (!BROKEN_BLOCK_STATES.contains(this.blockState))
|
||||||
{
|
{
|
||||||
LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biome + "] at pos: " + pos + ". Error: ["+e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e);
|
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);
|
BROKEN_BLOCK_STATES.add(this.blockState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,7 +548,7 @@ public class ClientBlockStateColorCache
|
|||||||
// helper classes //
|
// helper classes //
|
||||||
//================//
|
//================//
|
||||||
|
|
||||||
enum ColorMode
|
private enum EColorMode
|
||||||
{
|
{
|
||||||
Default,
|
Default,
|
||||||
Flower,
|
Flower,
|
||||||
@@ -551,7 +556,7 @@ public class ClientBlockStateColorCache
|
|||||||
Chisel,
|
Chisel,
|
||||||
Glass;
|
Glass;
|
||||||
|
|
||||||
static ColorMode getColorMode(Block block)
|
static EColorMode getColorMode(Block block)
|
||||||
{
|
{
|
||||||
if (block instanceof LeavesBlock) return Leaves;
|
if (block instanceof LeavesBlock) return Leaves;
|
||||||
if (block instanceof FlowerBlock) return Flower;
|
if (block instanceof FlowerBlock) return Flower;
|
||||||
|
|||||||
+8
-5
@@ -20,6 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.*;
|
import net.minecraft.world.level.*;
|
||||||
@@ -38,9 +39,9 @@ import java.util.Optional;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class TintGetterOverrideSmooth extends AbstractDhTintGetter
|
public class TintGetterOverride extends AbstractDhTintGetter
|
||||||
{
|
{
|
||||||
private final LevelReader parent;
|
private LevelReader parent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -48,9 +49,11 @@ public class TintGetterOverrideSmooth extends AbstractDhTintGetter
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public TintGetterOverrideSmooth(LevelReader parent, BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource)
|
public TintGetterOverride() { }
|
||||||
{
|
|
||||||
super(biomeWrapper, fullDataSource);
|
public void update(LevelReader parent, BiomeWrapper biomeWrapper, BlockStateWrapper blockStateWrapper, FullDataSourceV2 fullDataSource, IClientLevelWrapper clientLevelWrapper)
|
||||||
|
{
|
||||||
|
super.update(biomeWrapper, blockStateWrapper, fullDataSource, clientLevelWrapper);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
+12
-10
@@ -20,23 +20,25 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.block;
|
package com.seibel.distanthorizons.common.wrappers.block;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.LevelReader;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class TintWithoutLevelSmoothOverrider extends AbstractDhTintGetter
|
public class TintWithoutLevelOverrider extends AbstractDhTintGetter
|
||||||
{
|
{
|
||||||
|
|
||||||
//=============//
|
//=============//
|
||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public TintWithoutLevelSmoothOverrider(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource)
|
public TintWithoutLevelOverrider()
|
||||||
{ super(biomeWrapper, fullDataSource); }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -46,21 +48,21 @@ public class TintWithoutLevelSmoothOverrider extends AbstractDhTintGetter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getShade(Direction direction, boolean shade)
|
public float getShade(Direction direction, boolean shade)
|
||||||
{ throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
@Override
|
@Override
|
||||||
public LevelLightEngine getLightEngine()
|
public LevelLightEngine getLightEngine()
|
||||||
{ throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockEntity getBlockEntity(BlockPos pos)
|
public BlockEntity getBlockEntity(BlockPos pos)
|
||||||
{ throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlockState(BlockPos pos)
|
public BlockState getBlockState(BlockPos pos)
|
||||||
{ throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
@Override
|
@Override
|
||||||
public FluidState getFluidState(BlockPos pos)
|
public FluidState getFluidState(BlockPos pos)
|
||||||
{ throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
@@ -71,7 +73,7 @@ public class TintWithoutLevelSmoothOverrider extends AbstractDhTintGetter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHeight()
|
public int getHeight()
|
||||||
{ throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
@Override
|
@Override
|
||||||
@@ -80,7 +82,7 @@ public class TintWithoutLevelSmoothOverrider extends AbstractDhTintGetter
|
|||||||
#else
|
#else
|
||||||
@Override
|
@Override
|
||||||
public int getMinY()
|
public int getMinY()
|
||||||
{ throw new UnsupportedOperationException("ERROR: getMinY() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
|
{ throw new UnsupportedOperationException("ERROR: getMinY() called on TintWithoutLevelOverrider. Object is for tinting only."); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+64
-70
@@ -18,10 +18,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.seibel.distanthorizons.common.wrappers.chunk;
|
package com.seibel.distanthorizons.common.wrappers.chunk;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.DhApi;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.misc.MutableBlockPosWrapper;
|
import com.seibel.distanthorizons.common.wrappers.misc.MutableBlockPosWrapper;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
@@ -38,7 +38,7 @@ import net.minecraft.world.level.chunk.ChunkAccess;
|
|||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -75,12 +75,14 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|||||||
|
|
||||||
public class ChunkWrapper implements IChunkWrapper
|
public class ChunkWrapper implements IChunkWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
/** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */
|
/** can be used for interactions with the underlying chunk where creating new BlockPos objects could cause issues for the garbage collector. */
|
||||||
private static final ThreadLocal<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos());
|
private static final ThreadLocal<BlockPos.MutableBlockPos> MUTABLE_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos());
|
||||||
private static final ThreadLocal<MutableBlockPosWrapper> MUTABLE_BLOCK_POS_WRAPPER_REF = ThreadLocal.withInitial(() -> new MutableBlockPosWrapper());
|
private static final ThreadLocal<MutableBlockPosWrapper> MUTABLE_BLOCK_POS_WRAPPER_REF = ThreadLocal.withInitial(() -> new MutableBlockPosWrapper());
|
||||||
|
|
||||||
|
private static boolean heightmapThreadWarningLogged = false;
|
||||||
|
|
||||||
|
|
||||||
private final ChunkAccess chunk;
|
private final ChunkAccess chunk;
|
||||||
private final DhChunkPos chunkPos;
|
private final DhChunkPos chunkPos;
|
||||||
@@ -98,9 +100,9 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
private int maxNonEmptyHeight = Integer.MAX_VALUE;
|
private int maxNonEmptyHeight = Integer.MAX_VALUE;
|
||||||
|
|
||||||
/** will be null if we are using MC heightmaps */
|
/** will be null if we are using MC heightmaps */
|
||||||
private final int[][] solidHeightMap;
|
private int[][] solidHeightMap = null;
|
||||||
/** will be null if we are using MC heightmaps */
|
/** will be null if we are using MC heightmaps */
|
||||||
private final int[][] lightBlockingHeightMap;
|
private int[][] lightBlockingHeightMap = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -108,27 +110,21 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel)
|
public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel)
|
||||||
{
|
{
|
||||||
this.chunk = chunk;
|
this.chunk = chunk;
|
||||||
this.wrappedLevel = wrappedLevel;
|
this.wrappedLevel = wrappedLevel;
|
||||||
this.chunkPos = new DhChunkPos(chunk.getPos().x, chunk.getPos().z);
|
this.chunkPos = new DhChunkPos(chunk.getPos().x, chunk.getPos().z);
|
||||||
|
|
||||||
// use DH heightmaps if requested
|
|
||||||
if (Config.Common.LodBuilding.recalculateChunkHeightmaps.get())
|
|
||||||
{
|
|
||||||
this.solidHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
|
|
||||||
this.lightBlockingHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
|
|
||||||
|
|
||||||
this.recalculateDhHeightMapsIfNeeded();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.solidHeightMap = null;
|
|
||||||
this.lightBlockingHeightMap = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkWrapper copy() { return new ChunkWrapper(this.chunk, this.wrappedLevel); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=========//
|
//=========//
|
||||||
@@ -248,56 +244,63 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
}
|
}
|
||||||
private int getChunkSectionMinHeight(int index) { return (index * 16) + this.getInclusiveMinBuildHeight(); }
|
private int getChunkSectionMinHeight(int index) { return (index * 16) + this.getInclusiveMinBuildHeight(); }
|
||||||
|
|
||||||
/** Will only run if the config says the MC heightmaps shouldn't be trusted. */
|
@Override
|
||||||
public void recalculateDhHeightMapsIfNeeded()
|
public void createDhHeightMaps()
|
||||||
{
|
{
|
||||||
// re-calculate the min/max heights for consistency (during world gen these may be wrong)
|
if (heightmapThreadWarningLogged
|
||||||
this.minNonEmptyHeight = Integer.MIN_VALUE;
|
&& !DhApi.isDhThread())
|
||||||
this.maxNonEmptyHeight = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
|
|
||||||
// recalculate heightmaps if needed
|
|
||||||
if (this.solidHeightMap != null)
|
|
||||||
{
|
{
|
||||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
LOGGER.warn("ChunkWrapper Height maps created on non-DH thread ["+Thread.currentThread().getName()+"]. This may cause stuttering.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.solidHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
|
||||||
|
this.lightBlockingHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
|
||||||
|
|
||||||
|
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
int minInclusiveBuildHeight = this.getMinNonEmptyHeight();
|
||||||
|
// if no blocks are found the height map will be at the bottom of the world
|
||||||
|
int solidHeight = minInclusiveBuildHeight;
|
||||||
|
int lightBlockingHeight = minInclusiveBuildHeight;
|
||||||
|
|
||||||
|
|
||||||
|
int y = this.getMaxNonEmptyHeight(); //this.getExclusiveMaxBuildHeight();
|
||||||
|
IBlockStateWrapper block = this.getBlockState(x, y, z);
|
||||||
|
while (// go down until we reach the minimum build height
|
||||||
|
y > minInclusiveBuildHeight
|
||||||
|
// keep going until we find both height map values
|
||||||
|
&&
|
||||||
|
(
|
||||||
|
solidHeight == minInclusiveBuildHeight
|
||||||
|
|| lightBlockingHeight == minInclusiveBuildHeight
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
int minInclusiveBuildHeight = this.getMinNonEmptyHeight();
|
// is this block solid?
|
||||||
// if no blocks are found the height map will be at the bottom of the world
|
if (solidHeight == minInclusiveBuildHeight
|
||||||
int solidHeight = minInclusiveBuildHeight;
|
&& block.isSolid())
|
||||||
int lightBlockingHeight = minInclusiveBuildHeight;
|
|
||||||
|
|
||||||
|
|
||||||
int y = this.getMaxNonEmptyHeight(); //this.getExclusiveMaxBuildHeight();
|
|
||||||
IBlockStateWrapper block = this.getBlockState(x, y, z);
|
|
||||||
while (// go down until we reach the minimum build height
|
|
||||||
y > minInclusiveBuildHeight
|
|
||||||
// keep going until we find both height map values
|
|
||||||
&& (solidHeight == minInclusiveBuildHeight || lightBlockingHeight == minInclusiveBuildHeight))
|
|
||||||
{
|
{
|
||||||
// is this block solid?
|
solidHeight = y;
|
||||||
if (solidHeight == minInclusiveBuildHeight
|
|
||||||
&& block.isSolid())
|
|
||||||
{
|
|
||||||
solidHeight = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is this block light blocking?
|
|
||||||
if (lightBlockingHeight == minInclusiveBuildHeight
|
|
||||||
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
|
|
||||||
{
|
|
||||||
lightBlockingHeight = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the next block down
|
|
||||||
y--;
|
|
||||||
block = this.getBlockState(x, y, z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.solidHeightMap[x][z] = solidHeight;
|
// is this block light blocking?
|
||||||
this.lightBlockingHeightMap[x][z] = lightBlockingHeight;
|
if (lightBlockingHeight == minInclusiveBuildHeight
|
||||||
|
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
|
||||||
|
{
|
||||||
|
lightBlockingHeight = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next block down
|
||||||
|
y--;
|
||||||
|
block = this.getBlockState(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.solidHeightMap[x][z] = solidHeight;
|
||||||
|
this.lightBlockingHeightMap[x][z] = lightBlockingHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -617,15 +620,6 @@ public class ChunkWrapper implements IChunkWrapper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===============//
|
|
||||||
// other methods //
|
|
||||||
//===============//
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStillValid() { return this.wrappedLevel.tryGetChunk(this.chunkPos) == this; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// base overrides //
|
// base overrides //
|
||||||
//================//
|
//================//
|
||||||
|
|||||||
+196
-196
@@ -7,31 +7,22 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
// Logger (for debug stuff)
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui;
|
import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.gui.config.ConfigGuiInfo;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
import com.seibel.distanthorizons.core.config.types.*;
|
import com.seibel.distanthorizons.core.config.types.*;
|
||||||
import com.seibel.distanthorizons.common.wrappers.gui.updater.ChangelogScreen;
|
import com.seibel.distanthorizons.common.wrappers.gui.updater.ChangelogScreen;
|
||||||
|
|
||||||
// Uses https://github.com/TheElectronWill/night-config for toml (only for Fabric since Forge already includes this)
|
|
||||||
|
|
||||||
// Gets info from our own mod
|
|
||||||
|
|
||||||
// Minecraft imports
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosition;
|
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;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.logging.SpamReducedLogger;
|
|
||||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
|
||||||
import com.seibel.distanthorizons.core.util.AnnotationUtil;
|
import com.seibel.distanthorizons.core.util.AnnotationUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
|
||||||
@@ -46,10 +37,9 @@ import net.minecraft.client.gui.components.EditBox;
|
|||||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_1
|
#if MC_VER < MC_1_20_1
|
||||||
@@ -63,6 +53,12 @@ import net.minecraft.client.gui.GuiGraphics;
|
|||||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
||||||
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translatable;
|
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translatable;
|
||||||
|
|
||||||
@@ -81,8 +77,10 @@ import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translata
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ClassicConfigGUI
|
public class ClassicConfigGUI
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
public static final SpamReducedLogger SPAM_LOGGER = new SpamReducedLogger(4);
|
public static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
|
||||||
|
.maxCountPerSecond(1)
|
||||||
|
.build();
|
||||||
|
|
||||||
public static final ConfigCoreInterface CONFIG_CORE_INTERFACE = new ConfigCoreInterface();
|
public static final ConfigCoreInterface CONFIG_CORE_INTERFACE = new ConfigCoreInterface();
|
||||||
|
|
||||||
@@ -111,16 +109,6 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
/** The terribly coded old stuff */
|
|
||||||
public static class EntryInfo
|
|
||||||
{
|
|
||||||
Object widget;
|
|
||||||
Map.Entry<EditBox, Component> error;
|
|
||||||
String tempValue;
|
|
||||||
int index;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
@@ -128,10 +116,9 @@ public class ClassicConfigGUI
|
|||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
/** if you want to get this config gui's screen call this */
|
/** if you want to get this config gui's screen call this */
|
||||||
public static Screen getScreen(ConfigBase configBase, Screen parent, String category)
|
public static Screen getScreen(Screen parent, String category)
|
||||||
{ return new ConfigScreen(configBase, parent, category); }
|
{ return new ConfigScreen(parent, category); }
|
||||||
|
|
||||||
/** Pain */
|
|
||||||
private static class ConfigScreen extends DhScreen
|
private static class ConfigScreen extends DhScreen
|
||||||
{
|
{
|
||||||
private static final ILangWrapper LANG_WRAPPER = SingletonInjector.INSTANCE.get(ILangWrapper.class);
|
private static final ILangWrapper LANG_WRAPPER = SingletonInjector.INSTANCE.get(ILangWrapper.class);
|
||||||
@@ -139,8 +126,6 @@ public class ClassicConfigGUI
|
|||||||
private static final String TRANSLATION_PREFIX = ModInfo.ID + ".config.";
|
private static final String TRANSLATION_PREFIX = ModInfo.ID + ".config.";
|
||||||
|
|
||||||
|
|
||||||
private final ConfigBase configBase;
|
|
||||||
|
|
||||||
private final Screen parent;
|
private final Screen parent;
|
||||||
private final String category;
|
private final String category;
|
||||||
private ConfigListWidget configListWidget;
|
private ConfigListWidget configListWidget;
|
||||||
@@ -154,14 +139,13 @@ public class ClassicConfigGUI
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
protected ConfigScreen(ConfigBase configBase, Screen parent, String category)
|
protected ConfigScreen(Screen parent, String category)
|
||||||
{
|
{
|
||||||
super(Translatable(
|
super(Translatable(
|
||||||
LANG_WRAPPER.langExists(ModInfo.ID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ?
|
LANG_WRAPPER.langExists(ModInfo.ID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ?
|
||||||
ModInfo.ID + ".config.title" :
|
ModInfo.ID + ".config.title" :
|
||||||
ModInfo.ID + ".config" + (category.isEmpty() ? "" : "." + category) + ".title")
|
ModInfo.ID + ".config" + (category.isEmpty() ? "" : "." + category) + ".title")
|
||||||
);
|
);
|
||||||
this.configBase = configBase;
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.category = category;
|
this.category = category;
|
||||||
}
|
}
|
||||||
@@ -182,7 +166,7 @@ public class ClassicConfigGUI
|
|||||||
super.init();
|
super.init();
|
||||||
if (!this.reload)
|
if (!this.reload)
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileHandler.loadFromFile();
|
ConfigHandler.INSTANCE.configFileHandler.loadFromFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changelog button
|
// Changelog button
|
||||||
@@ -201,8 +185,10 @@ public class ClassicConfigGUI
|
|||||||
0,
|
0,
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER < MC_1_21_1
|
||||||
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
|
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
|
#else
|
||||||
|
Identifier.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
#endif
|
#endif
|
||||||
20, 20,
|
20, 20,
|
||||||
// Create the button and tell it where to go
|
// Create the button and tell it where to go
|
||||||
@@ -229,7 +215,7 @@ public class ClassicConfigGUI
|
|||||||
ConfigScreenConfigs.OPTION_FIELD_WIDTH, ConfigScreenConfigs.OPTION_FIELD_HEIGHT,
|
ConfigScreenConfigs.OPTION_FIELD_WIDTH, ConfigScreenConfigs.OPTION_FIELD_HEIGHT,
|
||||||
(button) ->
|
(button) ->
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileHandler.loadFromFile();
|
ConfigHandler.INSTANCE.configFileHandler.loadFromFile();
|
||||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -240,7 +226,7 @@ public class ClassicConfigGUI
|
|||||||
ConfigScreenConfigs.OPTION_FIELD_WIDTH, ConfigScreenConfigs.OPTION_FIELD_HEIGHT,
|
ConfigScreenConfigs.OPTION_FIELD_WIDTH, ConfigScreenConfigs.OPTION_FIELD_HEIGHT,
|
||||||
(button) ->
|
(button) ->
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileHandler.saveToFile();
|
ConfigHandler.INSTANCE.configFileHandler.saveToFile();
|
||||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -255,22 +241,22 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
this.addWidget(this.configListWidget);
|
this.addWidget(this.configListWidget);
|
||||||
|
|
||||||
for (AbstractConfigType info : ConfigBase.INSTANCE.entries)
|
for (AbstractConfigBase<?> configEntry : ConfigHandler.INSTANCE.configBaseList)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (info.getCategory().matches(this.category)
|
if (configEntry.getCategory().matches(this.category)
|
||||||
&& info.getAppearance().showInGui)
|
&& configEntry.getAppearance().showInGui)
|
||||||
{
|
{
|
||||||
this.addMenuItem(info);
|
this.addMenuItem(configEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
String message = "ERROR: Failed to show [" + info.getNameWCategory() + "], error: ["+e.getMessage()+"]";
|
String message = "ERROR: Failed to show [" + configEntry.getNameAndCategory() + "], error: ["+e.getMessage()+"]";
|
||||||
if (info.get() != null)
|
if (configEntry.get() != null)
|
||||||
{
|
{
|
||||||
message += " with the value [" + info.get() + "] with type [" + info.getType() + "]";
|
message += " with the value [" + configEntry.get() + "] with type [" + configEntry.getType() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.error(message, e);
|
LOGGER.error(message, e);
|
||||||
@@ -279,115 +265,63 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
|
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
|
||||||
}
|
}
|
||||||
private void addMenuItem(AbstractConfigType configType)
|
private void addMenuItem(AbstractConfigBase<?> configEntry)
|
||||||
{
|
{
|
||||||
trySetupConfigEntry(configType);
|
trySetupConfigEntry(configEntry);
|
||||||
|
|
||||||
if (this.tryCreateInputField(configType)) return;
|
if (this.tryCreateInputField(configEntry)) return;
|
||||||
if (this.tryCreateCategoryButton(configType)) return;
|
if (this.tryCreateCategoryButton(configEntry)) return;
|
||||||
if (this.tryCreateButton(configType)) return;
|
if (this.tryCreateButton(configEntry)) return;
|
||||||
if (this.tryCreateComment(configType)) return;
|
if (this.tryCreateComment(configEntry)) return;
|
||||||
if (this.tryCreateSpacer(configType)) return;
|
if (this.tryCreateSpacer(configEntry)) return;
|
||||||
if (this.tryCreateLinkedEntry(configType)) return;
|
if (this.tryCreateLinkedEntry(configEntry)) return;
|
||||||
|
|
||||||
LOGGER.warn("Config [" + configType.getNameWCategory() + "] failed to show. Please try something like changing its type.");
|
LOGGER.warn("Config [" + configEntry.getNameAndCategory() + "] failed to show. Please try something like changing its type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void trySetupConfigEntry(AbstractConfigType configType)
|
private static void trySetupConfigEntry(AbstractConfigBase<?> configMenuOption)
|
||||||
{
|
{
|
||||||
configType.guiValue = new EntryInfo();
|
configMenuOption.guiValue = new ConfigGuiInfo();
|
||||||
Class<?> fieldClass = configType.getType();
|
Class<?> configValueClass = configMenuOption.getType();
|
||||||
|
|
||||||
if (configType instanceof ConfigEntry)
|
if (configMenuOption instanceof ConfigEntry)
|
||||||
{
|
{
|
||||||
ConfigEntry configEntry = (ConfigEntry) configType;
|
ConfigEntry<?> configEntry = (ConfigEntry<?>) configMenuOption;
|
||||||
|
|
||||||
if (fieldClass == Integer.class)
|
if (configValueClass == Integer.class)
|
||||||
{
|
{
|
||||||
// For int
|
setupTextMenuOption(configEntry, Integer::parseInt, INTEGER_ONLY_REGEX, true);
|
||||||
setupEntryInfoTextField(configEntry, Integer::parseInt, INTEGER_ONLY_REGEX, true);
|
|
||||||
}
|
}
|
||||||
else if (fieldClass == Double.class)
|
else if (configValueClass == Double.class)
|
||||||
{
|
{
|
||||||
// For double
|
setupTextMenuOption(configEntry, Double::parseDouble, DECIMAL_ONLY_REGEX, false);
|
||||||
setupEntryInfoTextField(configEntry, Double::parseDouble, DECIMAL_ONLY_REGEX, false);
|
|
||||||
}
|
}
|
||||||
else if (fieldClass == String.class || fieldClass == List.class)
|
else if (configValueClass == String.class || configValueClass == List.class)
|
||||||
{
|
{
|
||||||
// For string or list
|
// For string or list
|
||||||
setupEntryInfoTextField(configEntry, String::length, null, true);
|
setupTextMenuOption(configEntry, String::length, null, true);
|
||||||
}
|
}
|
||||||
else if (fieldClass == Boolean.class)
|
else if (configValueClass == Boolean.class)
|
||||||
{
|
{
|
||||||
// For boolean
|
ConfigEntry<Boolean> booleanConfigEntry = (ConfigEntry<Boolean>) configEntry;
|
||||||
Function<Object, Component> func = value -> Translatable("distanthorizons.general."+((Boolean) value ? "true" : "false")).withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
|
setupBooleanMenuOption(booleanConfigEntry);
|
||||||
|
|
||||||
((EntryInfo) configEntry.guiValue).widget =
|
|
||||||
new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(
|
|
||||||
(button) ->
|
|
||||||
{
|
|
||||||
button.active = !configEntry.apiIsOverriding();
|
|
||||||
|
|
||||||
configEntry.uiSetWithoutSaving(!(Boolean) configEntry.get());
|
|
||||||
button.setMessage(func.apply(configEntry.get()));
|
|
||||||
}, func);
|
|
||||||
}
|
}
|
||||||
else if (fieldClass.isEnum())
|
else if (configValueClass.isEnum())
|
||||||
{
|
{
|
||||||
// For enum
|
ConfigEntry<Enum<?>> enumConfigEntry = (ConfigEntry<Enum<?>>) configEntry;
|
||||||
List<?> values = Arrays.asList(configEntry.getType().getEnumConstants());
|
Class<? extends Enum<?>> configEnumClass = (Class<? extends Enum<?>>) configValueClass;
|
||||||
Function<Object, Component> func = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + fieldClass.getSimpleName() + "." + configEntry.get().toString());
|
setupEnumMenuOption(enumConfigEntry, configEnumClass);
|
||||||
((EntryInfo) configEntry.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>((button) ->
|
|
||||||
{
|
|
||||||
// get the currently selected enum and enum index
|
|
||||||
int startingIndex = values.indexOf(configEntry.get());
|
|
||||||
Enum<?> enumValue = (Enum<?>) values.get(startingIndex);
|
|
||||||
|
|
||||||
// search for the next enum that is selectable
|
|
||||||
int index = startingIndex + 1;
|
|
||||||
index = (index >= values.size()) ? 0 : index;
|
|
||||||
while (index != startingIndex)
|
|
||||||
{
|
|
||||||
enumValue = (Enum<?>) values.get(index);
|
|
||||||
if (!AnnotationUtil.doesEnumHaveAnnotation(enumValue, DisallowSelectingViaConfigGui.class))
|
|
||||||
{
|
|
||||||
// this enum shouldn't be selectable via the UI,
|
|
||||||
// skip it
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
index = (index >= values.size()) ? 0 : index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == startingIndex)
|
|
||||||
{
|
|
||||||
// none of the enums should be selectable, this is a programmer error
|
|
||||||
enumValue = (Enum<?>) values.get(startingIndex);
|
|
||||||
LOGGER.warn("Enum [" + enumValue.getClass() + "] doesn't contain any values that should be selectable via the UI, sticking to the currently selected value [" + enumValue + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
((ConfigEntry<Enum<?>>) configEntry).uiSetWithoutSaving(enumValue);
|
|
||||||
|
|
||||||
if (configEntry.getApiValue() != null)
|
|
||||||
{
|
|
||||||
button.active = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
button.active = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.setMessage(func.apply(configEntry.get()));
|
|
||||||
}, func);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
private static void setupEntryInfoTextField(AbstractConfigType info, Function<String, Number> func, Pattern pattern, boolean cast)
|
private static void setupTextMenuOption(AbstractConfigBase<?> configMenuOption, Function<String, Number> parsingFunc, @Nullable Pattern pattern, boolean cast)
|
||||||
{
|
{
|
||||||
((EntryInfo) info.guiValue).widget = (BiFunction<EditBox, Button, Predicate<String>>) (editBox, button) -> stringValue ->
|
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) configMenuOption.guiValue);
|
||||||
|
|
||||||
|
configGuiInfo.tooltipFunction =
|
||||||
|
(editBox, button) ->
|
||||||
|
(stringValue) ->
|
||||||
{
|
{
|
||||||
boolean isNumber = (pattern != null);
|
boolean isNumber = (pattern != null);
|
||||||
|
|
||||||
@@ -398,67 +332,137 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Number value = info.typeIsFloatingPointNumber() ? 0.0 : 0; // different default values are needed so implicit casting works correctly (if not done casting from 0 (an int) to a double will cause an exception)
|
Number numberValue = configMenuOption.typeIsFloatingPointNumber() ? 0.0 : 0; // different default values are needed so implicit casting works correctly (if not done casting from 0 (an int) to a double will cause an exception)
|
||||||
((EntryInfo) info.guiValue).error = null;
|
configGuiInfo.errorMessage = null;
|
||||||
if (isNumber && !stringValue.isEmpty() && !stringValue.equals("-") && !stringValue.equals("."))
|
if (isNumber
|
||||||
|
&& !stringValue.isEmpty()
|
||||||
|
&& !stringValue.equals("-")
|
||||||
|
&& !stringValue.equals("."))
|
||||||
{
|
{
|
||||||
|
ConfigEntry<Number> numberConfigEntry = (ConfigEntry<Number>) configMenuOption;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
value = func.apply(stringValue);
|
numberValue = parsingFunc.apply(stringValue);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
value = null;
|
numberValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte isValid = ((ConfigEntry) info).isValid(value);
|
EConfigValidity validity = numberConfigEntry.getValidity(numberValue);
|
||||||
switch (isValid)
|
switch (validity)
|
||||||
{
|
{
|
||||||
case 0:
|
case VALID:
|
||||||
((EntryInfo) info.guiValue).error = null;
|
configGuiInfo.errorMessage = null;
|
||||||
break;
|
break;
|
||||||
case -1:
|
case NUMBER_TOO_LOW:
|
||||||
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry) info).getMin()));
|
configGuiInfo.errorMessage = TextOrTranslatable("§cMinimum length is " + numberConfigEntry.getMin());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case NUMBER_TOO_HIGH:
|
||||||
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry) info).getMax()));
|
configGuiInfo.errorMessage = TextOrTranslatable("§cMaximum length is " + numberConfigEntry.getMax());
|
||||||
break;
|
break;
|
||||||
case 2:
|
case INVALID:
|
||||||
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid"));
|
configGuiInfo.errorMessage = TextOrTranslatable("§cValue is invalid");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
((EntryInfo) info.guiValue).tempValue = stringValue;
|
editBox.setTextColor(((ConfigEntry<Number>) configMenuOption).getValidity(numberValue) == EConfigValidity.VALID ? 0xFFFFFFFF : 0xFFFF7777); // white and red
|
||||||
editBox.setTextColor(((ConfigEntry) info).isValid(value) == 0 ? 0xFFFFFFFF : 0xFFFF7777); // white and red
|
|
||||||
|
|
||||||
|
|
||||||
if (info.getType() == String.class
|
if (configMenuOption.getType() == String.class
|
||||||
|| info.getType() == List.class)
|
|| configMenuOption.getType() == List.class)
|
||||||
{
|
{
|
||||||
((ConfigEntry) info).uiSetWithoutSaving(stringValue);
|
((ConfigEntry<String>) configMenuOption).uiSetWithoutSaving(stringValue);
|
||||||
}
|
}
|
||||||
else if (((ConfigEntry) info).isValid(value) == 0)
|
else if (((ConfigEntry<Number>) configMenuOption).getValidity(numberValue) == EConfigValidity.VALID)
|
||||||
{
|
{
|
||||||
if (!cast)
|
if (!cast)
|
||||||
{
|
{
|
||||||
((ConfigEntry) info).uiSetWithoutSaving(value);
|
((ConfigEntry<Number>) configMenuOption).uiSetWithoutSaving(numberValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((ConfigEntry) info).uiSetWithoutSaving(value != null ? value.intValue() : 0);
|
((ConfigEntry<Number>) configMenuOption).uiSetWithoutSaving(numberValue != null ? numberValue.intValue() : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
private static void setupBooleanMenuOption(ConfigEntry<Boolean> booleanConfigEntry)
|
||||||
private boolean tryCreateInputField(AbstractConfigType configType)
|
|
||||||
{
|
{
|
||||||
if (configType instanceof ConfigEntry)
|
// For boolean
|
||||||
|
Function<Object, Component> func = value -> Translatable("distanthorizons.general."+((Boolean) value ? "true" : "false")).withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
|
||||||
|
|
||||||
|
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) booleanConfigEntry.guiValue);
|
||||||
|
|
||||||
|
configGuiInfo.buttonOptionMap =
|
||||||
|
new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(
|
||||||
|
(button) ->
|
||||||
|
{
|
||||||
|
button.active = !booleanConfigEntry.apiIsOverriding();
|
||||||
|
|
||||||
|
booleanConfigEntry.uiSetWithoutSaving(!booleanConfigEntry.get());
|
||||||
|
button.setMessage(func.apply(booleanConfigEntry.get()));
|
||||||
|
}, func);
|
||||||
|
}
|
||||||
|
private static void setupEnumMenuOption(ConfigEntry<Enum<?>> enumConfigEntry, Class<? extends Enum<?>> enumClass)
|
||||||
|
{
|
||||||
|
List<Enum<?>> enumList = Arrays.asList(enumClass.getEnumConstants());
|
||||||
|
|
||||||
|
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) enumConfigEntry.guiValue);
|
||||||
|
|
||||||
|
Function<Object, Component> getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString());
|
||||||
|
configGuiInfo.buttonOptionMap =
|
||||||
|
new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(
|
||||||
|
(button) ->
|
||||||
{
|
{
|
||||||
ConfigEntry configEntry = (ConfigEntry) configType;
|
// get the currently selected enum and enum index
|
||||||
|
int startingIndex = enumList.indexOf(enumConfigEntry.get());
|
||||||
|
Enum<?> enumValue = enumList.get(startingIndex);
|
||||||
|
|
||||||
|
// search for the next enum that is selectable
|
||||||
|
int index = startingIndex + 1;
|
||||||
|
index = (index >= enumList.size()) ? 0 : index;
|
||||||
|
while (index != startingIndex)
|
||||||
|
{
|
||||||
|
enumValue = enumList.get(index);
|
||||||
|
if (!AnnotationUtil.doesEnumHaveAnnotation(enumValue, DisallowSelectingViaConfigGui.class))
|
||||||
|
{
|
||||||
|
// this enum shouldn't be selectable via the UI,
|
||||||
|
// skip it
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
index = (index >= enumList.size()) ? 0 : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == startingIndex)
|
||||||
|
{
|
||||||
|
// none of the enums should be selectable, this is a programmer error
|
||||||
|
enumValue = enumList.get(startingIndex);
|
||||||
|
LOGGER.warn("Enum [" + enumValue.getClass() + "] doesn't contain any values that should be selectable via the UI, sticking to the currently selected value [" + enumValue + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enumConfigEntry.uiSetWithoutSaving(enumValue);
|
||||||
|
|
||||||
|
button.active = !enumConfigEntry.apiIsOverriding();
|
||||||
|
|
||||||
|
button.setMessage(getEnumTranslatableFunc.apply(enumConfigEntry.get()));
|
||||||
|
}, getEnumTranslatableFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryCreateInputField(AbstractConfigBase<?> configBase)
|
||||||
|
{
|
||||||
|
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) configBase.guiValue);
|
||||||
|
|
||||||
|
if (configBase instanceof ConfigEntry)
|
||||||
|
{
|
||||||
|
ConfigEntry configEntry = (ConfigEntry) configBase;
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
@@ -468,7 +472,6 @@ public class ClassicConfigGUI
|
|||||||
Button.OnPress btnAction = (button) ->
|
Button.OnPress btnAction = (button) ->
|
||||||
{
|
{
|
||||||
configEntry.uiSetWithoutSaving(configEntry.getDefaultValue());
|
configEntry.uiSetWithoutSaving(configEntry.getDefaultValue());
|
||||||
((EntryInfo) configEntry.guiValue).index = 0;
|
|
||||||
this.reload = true;
|
this.reload = true;
|
||||||
Objects.requireNonNull(this.minecraft).setScreen(this);
|
Objects.requireNonNull(this.minecraft).setScreen(this);
|
||||||
};
|
};
|
||||||
@@ -509,11 +512,11 @@ public class ClassicConfigGUI
|
|||||||
- ConfigScreenConfigs.OPTION_FIELD_WIDTH;
|
- ConfigScreenConfigs.OPTION_FIELD_WIDTH;
|
||||||
int optionFieldPosZ = 0;
|
int optionFieldPosZ = 0;
|
||||||
|
|
||||||
if (((EntryInfo) configEntry.guiValue).widget instanceof Map.Entry)
|
if (configGuiInfo.buttonOptionMap != null)
|
||||||
{
|
{
|
||||||
// enum/multi option input button
|
// enum/multi option input button
|
||||||
|
|
||||||
Map.Entry<Button.OnPress, Function<Object, Component>> widget = (Map.Entry<Button.OnPress, Function<Object, Component>>) ((EntryInfo) configEntry.guiValue).widget;
|
Map.Entry<Button.OnPress, Function<Object, Component>> widget = configGuiInfo.buttonOptionMap;
|
||||||
if (configEntry.getType().isEnum())
|
if (configEntry.getType().isEnum())
|
||||||
{
|
{
|
||||||
widget.setValue((value) -> Translatable(TRANSLATION_PREFIX + "enum." + configEntry.getType().getSimpleName() + "." + configEntry.get().toString()));
|
widget.setValue((value) -> Translatable(TRANSLATION_PREFIX + "enum." + configEntry.getType().getSimpleName() + "." + configEntry.get().toString()));
|
||||||
@@ -537,7 +540,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (((EntryInfo) configEntry.guiValue).widget != null)
|
else
|
||||||
{
|
{
|
||||||
// text box input
|
// text box input
|
||||||
|
|
||||||
@@ -548,7 +551,7 @@ public class ClassicConfigGUI
|
|||||||
widget.setMaxLength(ConfigScreenConfigs.OPTION_FIELD_WIDTH);
|
widget.setMaxLength(ConfigScreenConfigs.OPTION_FIELD_WIDTH);
|
||||||
widget.insertText(String.valueOf(configEntry.get()));
|
widget.insertText(String.valueOf(configEntry.get()));
|
||||||
|
|
||||||
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) ((EntryInfo) configEntry.guiValue).widget).apply(widget, this.doneButton);
|
Predicate<String> processor = configGuiInfo.tooltipFunction.apply(widget, this.doneButton);
|
||||||
widget.setFilter(processor);
|
widget.setFilter(processor);
|
||||||
|
|
||||||
this.configListWidget.addButton(this, configEntry, widget, resetButton, null, textComponent);
|
this.configListWidget.addButton(this, configEntry, widget, resetButton, null, textComponent);
|
||||||
@@ -559,7 +562,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean tryCreateCategoryButton(AbstractConfigType configType)
|
private boolean tryCreateCategoryButton(AbstractConfigBase<?> configType)
|
||||||
{
|
{
|
||||||
if (configType instanceof ConfigCategory)
|
if (configType instanceof ConfigCategory)
|
||||||
{
|
{
|
||||||
@@ -575,8 +578,8 @@ public class ClassicConfigGUI
|
|||||||
ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT,
|
ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT,
|
||||||
((button) ->
|
((button) ->
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileHandler.saveToFile();
|
ConfigHandler.INSTANCE.configFileHandler.saveToFile();
|
||||||
Objects.requireNonNull(this.minecraft).setScreen(ClassicConfigGUI.getScreen(this.configBase, this, configCategory.getDestination()));
|
Objects.requireNonNull(this.minecraft).setScreen(ClassicConfigGUI.getScreen(this, configCategory.getDestination()));
|
||||||
}));
|
}));
|
||||||
this.configListWidget.addButton(this, configType, widget, null, null, null);
|
this.configListWidget.addButton(this, configType, widget, null, null, null);
|
||||||
|
|
||||||
@@ -585,7 +588,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean tryCreateButton(AbstractConfigType configType)
|
private boolean tryCreateButton(AbstractConfigBase<?> configType)
|
||||||
{
|
{
|
||||||
if (configType instanceof ConfigUIButton)
|
if (configType instanceof ConfigUIButton)
|
||||||
{
|
{
|
||||||
@@ -606,7 +609,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean tryCreateComment(AbstractConfigType configType)
|
private boolean tryCreateComment(AbstractConfigBase<?> configType)
|
||||||
{
|
{
|
||||||
if (configType instanceof ConfigUIComment)
|
if (configType instanceof ConfigUIComment)
|
||||||
{
|
{
|
||||||
@@ -625,7 +628,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean tryCreateSpacer(AbstractConfigType configType)
|
private boolean tryCreateSpacer(AbstractConfigBase<?> configType)
|
||||||
{
|
{
|
||||||
if (configType instanceof ConfigUISpacer)
|
if (configType instanceof ConfigUISpacer)
|
||||||
{
|
{
|
||||||
@@ -642,7 +645,7 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private boolean tryCreateLinkedEntry(AbstractConfigType configType)
|
private boolean tryCreateLinkedEntry(AbstractConfigBase<?> configType)
|
||||||
{
|
{
|
||||||
if (configType instanceof ConfigUiLinkedEntry)
|
if (configType instanceof ConfigUiLinkedEntry)
|
||||||
{
|
{
|
||||||
@@ -654,8 +657,8 @@ public class ClassicConfigGUI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component GetTranslatableTextComponentForConfig(AbstractConfigType configType)
|
private Component GetTranslatableTextComponentForConfig(AbstractConfigBase<?> configType)
|
||||||
{ return Translatable(TRANSLATION_PREFIX + configType.getNameWCategory());}
|
{ return Translatable(TRANSLATION_PREFIX + configType.getNameAndCategory());}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -729,33 +732,32 @@ public class ClassicConfigGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Component text = ButtonEntry.TEXT_BY_WIDGET.get(hoveredWidget);
|
|
||||||
ButtonEntry button = ButtonEntry.BUTTON_BY_WIDGET.get(hoveredWidget);
|
ButtonEntry button = ButtonEntry.BUTTON_BY_WIDGET.get(hoveredWidget);
|
||||||
|
|
||||||
|
|
||||||
// A quick fix for tooltips on linked entries
|
// A quick fix for tooltips on linked entries
|
||||||
AbstractConfigType dhConfigType = ConfigUiLinkedEntry.class.isAssignableFrom(button.dhConfigType.getClass()) ?
|
AbstractConfigBase<?> configBase = ConfigUiLinkedEntry.class.isAssignableFrom(button.dhConfigType.getClass()) ?
|
||||||
((ConfigUiLinkedEntry) button.dhConfigType).get() :
|
((ConfigUiLinkedEntry) button.dhConfigType).get() :
|
||||||
button.dhConfigType;
|
button.dhConfigType;
|
||||||
|
|
||||||
boolean apiOverrideActive = false;
|
boolean apiOverrideActive = false;
|
||||||
if (dhConfigType instanceof ConfigEntry)
|
if (configBase instanceof ConfigEntry)
|
||||||
{
|
{
|
||||||
apiOverrideActive = ((ConfigEntry)dhConfigType).apiIsOverriding();
|
apiOverrideActive = ((ConfigEntry<?>)configBase).apiIsOverriding();
|
||||||
}
|
}
|
||||||
|
|
||||||
Component name = Translatable(TRANSLATION_PREFIX + (dhConfigType.category.isEmpty() ? "" : dhConfigType.category + ".") + dhConfigType.getName());
|
String key = TRANSLATION_PREFIX + (configBase.category.isEmpty() ? "" : configBase.category + ".") + configBase.getName() + ".@tooltip";
|
||||||
String key = TRANSLATION_PREFIX + (dhConfigType.category.isEmpty() ? "" : dhConfigType.category + ".") + dhConfigType.getName() + ".@tooltip";
|
|
||||||
|
|
||||||
if (apiOverrideActive)
|
if (apiOverrideActive)
|
||||||
{
|
{
|
||||||
key = "distanthorizons.general.disabledByApi.@tooltip";
|
key = "distanthorizons.general.disabledByApi.@tooltip";
|
||||||
}
|
}
|
||||||
|
|
||||||
// display the validation error if present
|
// display the validation error tooltip if present
|
||||||
if (((EntryInfo) dhConfigType.guiValue).error != null)
|
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) configBase.guiValue);
|
||||||
|
if (configGuiInfo.errorMessage != null)
|
||||||
{
|
{
|
||||||
this.DhRenderTooltip(matrices, this.font, ((EntryInfo) dhConfigType.guiValue).error.getValue(), mouseX, mouseY);
|
this.DhRenderTooltip(matrices, this.font, configGuiInfo.errorMessage, mouseX, mouseY);
|
||||||
}
|
}
|
||||||
// display the tooltip if present
|
// display the tooltip if present
|
||||||
else if (LANG_WRAPPER.langExists(key))
|
else if (LANG_WRAPPER.langExists(key))
|
||||||
@@ -781,7 +783,7 @@ public class ClassicConfigGUI
|
|||||||
@Override
|
@Override
|
||||||
public void onClose()
|
public void onClose()
|
||||||
{
|
{
|
||||||
ConfigBase.INSTANCE.configFileHandler.saveToFile();
|
ConfigHandler.INSTANCE.configFileHandler.saveToFile();
|
||||||
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
|
||||||
|
|
||||||
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
|
CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
|
||||||
@@ -792,9 +794,9 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
|
||||||
public static class ConfigListWidget extends ContainerObjectSelectionList<ButtonEntry>
|
public static class ConfigListWidget extends ContainerObjectSelectionList<ButtonEntry>
|
||||||
{
|
{
|
||||||
@@ -812,7 +814,7 @@ public class ClassicConfigGUI
|
|||||||
this.textRenderer = minecraftClient.font;
|
this.textRenderer = minecraftClient.font;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addButton(ConfigScreen gui, AbstractConfigType dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text)
|
public void addButton(ConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text)
|
||||||
{ this.addEntry(new ButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton)); }
|
{ this.addEntry(new ButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton)); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -858,7 +860,7 @@ public class ClassicConfigGUI
|
|||||||
private final AbstractWidget button;
|
private final AbstractWidget button;
|
||||||
|
|
||||||
private final ConfigScreen gui;
|
private final ConfigScreen gui;
|
||||||
private final AbstractConfigType dhConfigType;
|
private final AbstractConfigBase dhConfigType;
|
||||||
|
|
||||||
private final AbstractWidget resetButton;
|
private final AbstractWidget resetButton;
|
||||||
private final AbstractWidget indexButton;
|
private final AbstractWidget indexButton;
|
||||||
@@ -869,12 +871,12 @@ public class ClassicConfigGUI
|
|||||||
private final EConfigCommentTextPosition textPosition;
|
private final EConfigCommentTextPosition textPosition;
|
||||||
|
|
||||||
public static final Map<AbstractWidget, Component> TEXT_BY_WIDGET = new HashMap<>();
|
public static final Map<AbstractWidget, Component> TEXT_BY_WIDGET = new HashMap<>();
|
||||||
// TODO we should just use a wrapper or something
|
/// TODO we should just use a wrapper or something
|
||||||
public static final Map<AbstractWidget, ButtonEntry> BUTTON_BY_WIDGET = new HashMap<>();
|
public static final Map<AbstractWidget, ButtonEntry> BUTTON_BY_WIDGET = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ButtonEntry(ConfigScreen gui, AbstractConfigType dhConfigType,
|
public ButtonEntry(ConfigScreen gui, AbstractConfigBase dhConfigType,
|
||||||
AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
|
AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
|
||||||
{
|
{
|
||||||
TEXT_BY_WIDGET.put(button, text);
|
TEXT_BY_WIDGET.put(button, text);
|
||||||
@@ -920,7 +922,7 @@ public class ClassicConfigGUI
|
|||||||
@Override
|
@Override
|
||||||
#if MC_VER < MC_1_20_1
|
#if 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)
|
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_10
|
#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)
|
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||||
#else
|
#else
|
||||||
public void renderContent(GuiGraphics matrices, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
public void renderContent(GuiGraphics matrices, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||||
@@ -928,9 +930,9 @@ public class ClassicConfigGUI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
#else
|
#else
|
||||||
int y = this.getY(); // TODO why is the Y value being set during render?
|
int y = this.getY(); /// TODO why is the Y value being set during render?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (this.button != null)
|
if (this.button != null)
|
||||||
@@ -1008,7 +1010,7 @@ public class ClassicConfigGUI
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// should prevent crashing the game if there's an issue
|
// should prevent crashing the game if there's an issue
|
||||||
SPAM_LOGGER.error("Unexpected gui rendering issue: ["+e.getMessage()+"]", e);
|
RATE_LIMITED_LOGGER.error("Unexpected gui rendering issue: ["+e.getMessage()+"]", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,13 +1030,11 @@ public class ClassicConfigGUI
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// event handling //
|
// event handling //
|
||||||
//================//
|
//================//
|
||||||
|
|
||||||
private static class ConfigCoreInterface implements IConfigGui
|
public static class ConfigCoreInterface implements IConfigGui
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* in the future it would be good to pass in the current page and other variables,
|
* in the future it would be good to pass in the current page and other variables,
|
||||||
|
|||||||
+12
-3
@@ -1,6 +1,6 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
// not supported for older MC versions
|
// not supported for older MC versions
|
||||||
#else
|
#else
|
||||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
@@ -14,12 +14,16 @@ import java.util.List;
|
|||||||
|
|
||||||
import net.minecraft.client.gui.components.debug.DebugScreenDisplayer;
|
import net.minecraft.client.gui.components.debug.DebugScreenDisplayer;
|
||||||
import net.minecraft.client.gui.components.debug.DebugScreenEntries;
|
import net.minecraft.client.gui.components.debug.DebugScreenEntries;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_10
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_9
|
||||||
// not supported for older MC versions
|
// not supported for older MC versions
|
||||||
public class DhDebugScreenEntry
|
public class DhDebugScreenEntry
|
||||||
{}
|
{}
|
||||||
@@ -31,7 +35,12 @@ public class DhDebugScreenEntry implements net.minecraft.client.gui.components.d
|
|||||||
// This method is private, so its access will need to be widened
|
// This method is private, so its access will need to be widened
|
||||||
DebugScreenEntries.register(
|
DebugScreenEntries.register(
|
||||||
// The id, this will be displayed on the options screen
|
// The id, this will be displayed on the options screen
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, "distant_horizons"),
|
ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, "distant_horizons"),
|
||||||
|
#else
|
||||||
|
"distant_horizons",
|
||||||
|
#endif
|
||||||
|
|
||||||
// The screen entry
|
// The screen entry
|
||||||
new DhDebugScreenEntry()
|
new DhDebugScreenEntry()
|
||||||
);
|
);
|
||||||
|
|||||||
+5
-7
@@ -1,17 +1,15 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
|
||||||
import com.seibel.distanthorizons.core.config.gui.JavaScreenHandlerScreen;
|
import com.seibel.distanthorizons.core.config.gui.JavaScreenHandlerScreen;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
|
|
||||||
public class GetConfigScreen
|
public class GetConfigScreen
|
||||||
{
|
{
|
||||||
protected static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
protected static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
public static EType useScreen = EType.Classic;
|
public static EType useScreen = EType.Classic;
|
||||||
|
|
||||||
@@ -28,7 +26,7 @@ public class GetConfigScreen
|
|||||||
// which won't be for sure added until we request a GUI
|
// which won't be for sure added until we request a GUI
|
||||||
if (ModInfo.IS_DEV_BUILD)
|
if (ModInfo.IS_DEV_BUILD)
|
||||||
{
|
{
|
||||||
String missingLangEntries = ConfigBase.INSTANCE.generateLang(true, true);
|
String missingLangEntries = ConfigHandler.INSTANCE.generateLang(true, true);
|
||||||
|
|
||||||
// trim to remove any newlines/spaces
|
// trim to remove any newlines/spaces
|
||||||
// that may be present when no lang entries need changing
|
// that may be present when no lang entries need changing
|
||||||
@@ -45,7 +43,7 @@ public class GetConfigScreen
|
|||||||
switch (useScreen)
|
switch (useScreen)
|
||||||
{
|
{
|
||||||
case Classic:
|
case Classic:
|
||||||
return ClassicConfigGUI.getScreen(ConfigBase.INSTANCE, parent, "client");
|
return ClassicConfigGUI.getScreen(parent, "client");
|
||||||
case JavaSwing:
|
case JavaSwing:
|
||||||
//return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
|
//return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
|
||||||
return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
|
return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
|
||||||
|
|||||||
+14
-2
@@ -39,7 +39,7 @@ public class MinecraftScreen
|
|||||||
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName)
|
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName)
|
||||||
{
|
{
|
||||||
super(translate(translationName));
|
super(translate(translationName));
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
|
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
|
||||||
#else
|
#else
|
||||||
screen.minecraftWindow = Minecraft.getInstance().getWindow().handle();
|
screen.minecraftWindow = Minecraft.getInstance().getWindow().handle();
|
||||||
@@ -95,10 +95,22 @@ public class MinecraftScreen
|
|||||||
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
|
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
@Override
|
@Override
|
||||||
public void resize(Minecraft mc, int width, int height)
|
public void resize(Minecraft mc, int width, int height)
|
||||||
|
#else
|
||||||
|
@Override
|
||||||
|
public void resize(int width, int height)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
super.resize(mc, width, height); // Resize Minecraft's screen
|
// Resize Minecraft's screen
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
super.resize(mc, width, height);
|
||||||
|
#else
|
||||||
|
super.resize(width, height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Window mcWindow = this.minecraft.getWindow();
|
Window mcWindow = this.minecraft.getWindow();
|
||||||
this.screen.width = mcWindow.getWidth();
|
this.screen.width = mcWindow.getWidth();
|
||||||
this.screen.height = mcWindow.getHeight();
|
this.screen.height = mcWindow.getHeight();
|
||||||
|
|||||||
+32
-4
@@ -20,7 +20,6 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.gui;
|
package com.seibel.distanthorizons.common.wrappers.gui;
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_17_1
|
#if MC_VER >= MC_1_17_1
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
@@ -42,10 +41,19 @@ import net.minecraft.client.gui.GuiGraphics;
|
|||||||
#elif MC_VER < MC_1_21_6
|
#elif MC_VER < MC_1_21_6
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.RenderPipelines;
|
import net.minecraft.client.renderer.RenderPipelines;
|
||||||
|
#else
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.renderer.RenderPipelines;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,18 +75,33 @@ public class TexturedButtonWidget extends Button
|
|||||||
private final int v;
|
private final int v;
|
||||||
private final int hoveredVOffset;
|
private final int hoveredVOffset;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
private final ResourceLocation textureResourceLocation;
|
private final ResourceLocation textureResourceLocation;
|
||||||
|
#else
|
||||||
|
private final Identifier textureResourceLocation;
|
||||||
|
#endif
|
||||||
|
|
||||||
private final int textureWidth;
|
private final int textureWidth;
|
||||||
private final int textureHeight;
|
private final int textureHeight;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true);
|
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, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
|
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)
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_20_2
|
#if MC_VER < MC_1_20_2
|
||||||
super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text);
|
super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text);
|
||||||
@@ -169,8 +192,13 @@ public class TexturedButtonWidget extends Button
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
#if MC_VER < MC_1_21_11
|
||||||
@Override
|
@Override
|
||||||
public void renderWidget(GuiGraphics matrices, int mouseX, int mouseY, float delta)
|
public void renderWidget(GuiGraphics matrices, int mouseX, int mouseY, float delta)
|
||||||
|
#else
|
||||||
|
@Override
|
||||||
|
protected void renderContents(GuiGraphics matrices, int mouseX, int mouseY, float delta)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (this.renderBackground)
|
if (this.renderBackground)
|
||||||
{
|
{
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package com.seibel.distanthorizons.common.wrappers.gui.config;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.config.gui.IConfigGuiInfo;
|
||||||
|
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
|
||||||
|
import net.minecraft.client.gui.components.Button;
|
||||||
|
import net.minecraft.client.gui.components.EditBox;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* holds information needed by the config GUI for rendering.
|
||||||
|
*
|
||||||
|
* @see AbstractConfigBase
|
||||||
|
*/
|
||||||
|
public class ConfigGuiInfo implements IConfigGuiInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used to display validation errors.
|
||||||
|
* Null if no error is present.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Component errorMessage;
|
||||||
|
|
||||||
|
public BiFunction<EditBox, Button, Predicate<String>> tooltipFunction;
|
||||||
|
/** determines which options the button will show */
|
||||||
|
public AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>> buttonOptionMap;
|
||||||
|
|
||||||
|
}
|
||||||
+3
-3
@@ -14,7 +14,7 @@ import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
|||||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_17_1
|
#if MC_VER >= MC_1_17_1
|
||||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||||
@@ -41,7 +41,7 @@ import java.util.*;
|
|||||||
// TODO: Make this
|
// TODO: Make this
|
||||||
public class ChangelogScreen extends DhScreen
|
public class ChangelogScreen extends DhScreen
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
private Screen parent;
|
private Screen parent;
|
||||||
@@ -262,7 +262,7 @@ public class ChangelogScreen extends DhScreen
|
|||||||
@Override
|
@Override
|
||||||
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||||
{ GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF); }
|
{ GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF); }
|
||||||
#elif MC_VER < MC_1_21_10
|
#elif MC_VER < MC_1_21_9
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||||
{ matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFF); }
|
{ matrices.drawString(textRenderer, this.text, 12, y + 5, 0xFFFFFF); }
|
||||||
|
|||||||
+18
-7
@@ -9,14 +9,21 @@ import com.seibel.distanthorizons.coreapi.ModInfo;
|
|||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
||||||
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER >= MC_1_20_1
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
#else
|
#else
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.apache.logging.log4j.Logger;
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
|
||||||
|
|
||||||
@@ -31,7 +38,7 @@ import java.util.*;
|
|||||||
// and also maybe add this suggestion https://discord.com/channels/881614130614767666/1035863487110467625/1035949054485594192
|
// and also maybe add this suggestion https://discord.com/channels/881614130614767666/1035863487110467625/1035949054485594192
|
||||||
public class UpdateModScreen extends DhScreen
|
public class UpdateModScreen extends DhScreen
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
private Screen parent;
|
private Screen parent;
|
||||||
@@ -88,10 +95,12 @@ public class UpdateModScreen extends DhScreen
|
|||||||
0, 0,
|
0, 0,
|
||||||
// Some textuary stuff
|
// Some textuary stuff
|
||||||
0,
|
0,
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER <= MC_1_20_6
|
||||||
new ResourceLocation(ModInfo.ID, "logo.png"),
|
new ResourceLocation(ModInfo.ID, "logo.png"),
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "logo.png"),
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "logo.png"),
|
||||||
|
#else
|
||||||
|
Identifier.fromNamespaceAndPath(ModInfo.ID, "logo.png"),
|
||||||
#endif
|
#endif
|
||||||
195, 65,
|
195, 65,
|
||||||
// Create the button and tell it where to go
|
// Create the button and tell it where to go
|
||||||
@@ -121,12 +130,14 @@ public class UpdateModScreen extends DhScreen
|
|||||||
0,
|
0,
|
||||||
#if MC_VER < MC_1_21_1
|
#if MC_VER < MC_1_21_1
|
||||||
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
|
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
|
#else
|
||||||
|
Identifier.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
|
||||||
#endif
|
#endif
|
||||||
20, 20,
|
20, 20,
|
||||||
// Create the button and tell it where to go
|
// Create the button and tell it where to go
|
||||||
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
|
(buttonWidget) -> Objects.requireNonNull(this.minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)),
|
||||||
// Add a title to the button
|
// Add a title to the button
|
||||||
Translatable(ModInfo.ID + ".updater.title")
|
Translatable(ModInfo.ID + ".updater.title")
|
||||||
));
|
));
|
||||||
|
|||||||
+2
-2
@@ -36,9 +36,9 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
|
|||||||
public IServerKeyedClientLevel getServerKeyedLevel() { return this.serverKeyedLevel; }
|
public IServerKeyedClientLevel getServerKeyedLevel() { return this.serverKeyedLevel; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String levelKey)
|
public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String serverKey, String levelKey)
|
||||||
{
|
{
|
||||||
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevel((ClientLevel) clientLevel.getWrappedMcObject(), levelKey);
|
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevelWrapper((ClientLevel) clientLevel.getWrappedMcObject(), serverKey, levelKey);
|
||||||
this.serverKeyedLevel = keyedLevel;
|
this.serverKeyedLevel = keyedLevel;
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
return keyedLevel;
|
return keyedLevel;
|
||||||
|
|||||||
+18
-4
@@ -2,24 +2,36 @@ package com.seibel.distanthorizons.common.wrappers.level;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
|
||||||
public class ServerKeyedClientLevel extends ClientLevelWrapper implements IServerKeyedClientLevel
|
public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements IServerKeyedClientLevel
|
||||||
{
|
{
|
||||||
|
/** Returns the folder name the server wants the client to use. */
|
||||||
|
private final String serverKey;
|
||||||
|
|
||||||
/** A unique identifier (generally the level's name) for differentiating multiverse levels */
|
/** A unique identifier (generally the level's name) for differentiating multiverse levels */
|
||||||
private final String serverLevelKey;
|
private final String serverLevelKey;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ServerKeyedClientLevel(ClientLevel level, String serverLevelKey)
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public ServerKeyedClientLevelWrapper(ClientLevel level, String serverKey, String serverLevelKey)
|
||||||
{
|
{
|
||||||
super(level);
|
super(level);
|
||||||
|
this.serverKey = serverKey;
|
||||||
this.serverLevelKey = serverLevelKey;
|
this.serverLevelKey = serverLevelKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerKey() { return this.serverKey; }
|
||||||
|
|
||||||
|
//======================//
|
||||||
|
// level identification //
|
||||||
|
//======================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getServerLevelKey() { return this.serverLevelKey; }
|
public String getServerLevelKey() { return this.serverLevelKey; }
|
||||||
@@ -27,4 +39,6 @@ public class ServerKeyedClientLevel extends ClientLevelWrapper implements IServe
|
|||||||
@Override
|
@Override
|
||||||
public String getDhIdentifier() { return this.getServerLevelKey(); }
|
public String getDhIdentifier() { return this.getServerLevelKey(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+122
-177
@@ -20,18 +20,8 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
package com.seibel.distanthorizons.common.wrappers.minecraft;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
|
||||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
|
||||||
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
@@ -40,25 +30,25 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
|
||||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import net.minecraft.CrashReport;
|
import net.minecraft.CrashReport;
|
||||||
|
import net.minecraft.client.CloudStatus;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.multiplayer.ServerData;
|
import net.minecraft.client.multiplayer.ServerData;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
import net.minecraft.network.chat.TextComponent;
|
import net.minecraft.network.chat.TextComponent;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.util.profiling.ProfilerFiller;
|
|
||||||
import net.minecraft.world.level.ChunkPos;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
#else
|
#else
|
||||||
@@ -72,95 +62,34 @@ import net.minecraft.util.profiling.Profiler;
|
|||||||
*/
|
*/
|
||||||
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
|
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||||
|
|
||||||
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
|
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The lightmap for the current:
|
|
||||||
* Time, dimension, brightness setting, etc.
|
|
||||||
*/
|
|
||||||
private NativeImage lightMap = null;
|
|
||||||
|
|
||||||
private ProfilerWrapper profilerWrapper;
|
private ProfilerWrapper profilerWrapper;
|
||||||
|
|
||||||
|
|
||||||
private MinecraftClientWrapper()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//======================//
|
||||||
|
// multiplayer handling //
|
||||||
//================//
|
//======================//
|
||||||
// helper methods //
|
|
||||||
//================//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This should be called at the beginning of every frame to
|
|
||||||
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
|
|
||||||
* <p>
|
|
||||||
* LightMaps and other time sensitive objects fall in this category. <br> <br>
|
|
||||||
* <p>
|
|
||||||
* This doesn't affect OpenGL objects in any way.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void clearFrameObjectCache() { this.lightMap = null; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=================//
|
|
||||||
// method wrappers //
|
|
||||||
//=================//
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getShade(EDhDirection lodDirection)
|
|
||||||
{
|
|
||||||
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
|
|
||||||
switch (lodShading)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case AUTO:
|
|
||||||
if (MINECRAFT.level != null)
|
|
||||||
{
|
|
||||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
|
||||||
return MINECRAFT.level.getShade(mcDir, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ENABLED:
|
|
||||||
switch (lodDirection)
|
|
||||||
{
|
|
||||||
case DOWN:
|
|
||||||
return 0.5F;
|
|
||||||
default:
|
|
||||||
case UP:
|
|
||||||
return 1.0F;
|
|
||||||
case NORTH:
|
|
||||||
case SOUTH:
|
|
||||||
return 0.8F;
|
|
||||||
case WEST:
|
|
||||||
case EAST:
|
|
||||||
return 0.6F;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DISABLED:
|
|
||||||
return 1.0F;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); }
|
public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); }
|
||||||
@Override
|
@Override
|
||||||
public boolean clientConnectedToDedicatedServer() { return MINECRAFT.getCurrentServer() != null && !this.hasSinglePlayerServer(); }
|
public boolean clientConnectedToDedicatedServer()
|
||||||
|
{
|
||||||
|
return MINECRAFT.getCurrentServer() != null
|
||||||
|
&& !this.hasSinglePlayerServer();
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean connectedToReplay() { return !MINECRAFT.hasSingleplayerServer() && MINECRAFT.getCurrentServer() == null; }
|
public boolean connectedToReplay()
|
||||||
|
{
|
||||||
|
return MINECRAFT.getCurrentServer() == null
|
||||||
|
&& !this.hasSinglePlayerServer() ;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentServerName()
|
public String getCurrentServerName()
|
||||||
@@ -175,7 +104,6 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
return (server != null) ? server.name : "NULL";
|
return (server != null) ? server.name : "NULL";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentServerIp()
|
public String getCurrentServerIp()
|
||||||
{
|
{
|
||||||
@@ -189,7 +117,6 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
return (server != null) ? server.ip : "NA";
|
return (server != null) ? server.ip : "NA";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentServerVersion()
|
public String getCurrentServerVersion()
|
||||||
{
|
{
|
||||||
@@ -197,21 +124,17 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
return (server != null) ? server.version.getString() : "UNKOWN";
|
return (server != null) ? server.version.getString() : "UNKOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============//
|
|
||||||
// Simple gets //
|
|
||||||
//=============//
|
//=================//
|
||||||
|
// player handling //
|
||||||
|
//=================//
|
||||||
|
|
||||||
public LocalPlayer getPlayer() { return MINECRAFT.player; }
|
public LocalPlayer getPlayer() { return MINECRAFT.player; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean playerExists() { return MINECRAFT.player != null; }
|
public boolean playerExists() { return MINECRAFT.player != null; }
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getPlayerUUID() { return this.getPlayer().getUUID(); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() { return MINECRAFT.getUser().getName(); }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DhBlockPos getPlayerBlockPos()
|
public DhBlockPos getPlayerBlockPos()
|
||||||
{
|
{
|
||||||
@@ -242,6 +165,12 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
return new DhChunkPos(playerPos.x, playerPos.z);
|
return new DhChunkPos(playerPos.x, playerPos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// level handling //
|
||||||
|
//================//
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public IClientLevelWrapper getWrappedClientLevel() { return this.getWrappedClientLevel(false); }
|
public IClientLevelWrapper getWrappedClientLevel() { return this.getWrappedClientLevel(false); }
|
||||||
@@ -259,6 +188,80 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
return ClientLevelWrapper.getWrapper(level, bypassLevelKeyManager);
|
return ClientLevelWrapper.getWrapper(level, bypassLevelKeyManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// messaging //
|
||||||
|
//===========//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendChatMessage(String string)
|
||||||
|
{
|
||||||
|
LocalPlayer player = this.getPlayer();
|
||||||
|
if (player == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 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);
|
||||||
|
#else
|
||||||
|
|
||||||
|
GLProxy.queueRunningOnRenderThread(() ->
|
||||||
|
{
|
||||||
|
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendOverlayMessage(String string)
|
||||||
|
{
|
||||||
|
LocalPlayer player = this.getPlayer();
|
||||||
|
if (player == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
player.displayClientMessage(new TextComponent(string), /*isOverlay*/true);
|
||||||
|
#else
|
||||||
|
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========================//
|
||||||
|
// vanilla option overrides //
|
||||||
|
//==========================//
|
||||||
|
|
||||||
|
public void disableVanillaClouds()
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_18_2
|
||||||
|
MINECRAFT.options.renderClouds = CloudStatus.OFF;
|
||||||
|
#else
|
||||||
|
MINECRAFT.options.cloudStatus().set(CloudStatus.OFF);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disableVanillaChunkFadeIn()
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
// chunk fade in was added MC 1.21.11
|
||||||
|
#else
|
||||||
|
MINECRAFT.options.chunkSectionFadeInTime().set(0.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======//
|
||||||
|
// misc //
|
||||||
|
//======//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IProfilerWrapper getProfiler()
|
public IProfilerWrapper getProfiler()
|
||||||
{
|
{
|
||||||
@@ -281,99 +284,39 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
return this.profilerWrapper;
|
return this.profilerWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns all worlds available to the server */
|
|
||||||
@Override
|
|
||||||
public ArrayList<ILevelWrapper> getAllServerWorlds()
|
|
||||||
{
|
|
||||||
ArrayList<ILevelWrapper> worlds = new ArrayList<ILevelWrapper>();
|
|
||||||
|
|
||||||
Iterable<ServerLevel> serverWorlds = MINECRAFT.getSingleplayerServer().getAllLevels();
|
|
||||||
for (ServerLevel world : serverWorlds)
|
|
||||||
{
|
|
||||||
worlds.add(ServerLevelWrapper.getWrapper(world));
|
|
||||||
}
|
|
||||||
|
|
||||||
return worlds;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendChatMessage(String string)
|
|
||||||
{
|
|
||||||
LocalPlayer player = this.getPlayer();
|
|
||||||
if (player == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GLProxy.hasInstance())
|
|
||||||
{
|
|
||||||
// rendering setup hasn't finished
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
player.sendMessage(new TextComponent(string), getPlayer().getUUID());
|
|
||||||
#elif MC_VER < MC_1_21_10
|
|
||||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
|
|
||||||
#else
|
|
||||||
|
|
||||||
GLProxy.getInstance().queueRunningOnRenderThread(() ->
|
|
||||||
{
|
|
||||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendOverlayMessage(String string)
|
|
||||||
{
|
|
||||||
LocalPlayer player = this.getPlayer();
|
|
||||||
if (player == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
player.displayClientMessage(new TextComponent(string), /*isOverlay*/true);
|
|
||||||
#else
|
|
||||||
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/true);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crashes Minecraft, displaying the given errorMessage <br> <br>
|
|
||||||
* In the following format: <br>
|
|
||||||
*
|
|
||||||
* The game crashed whilst <strong>errorMessage</strong> <br>
|
|
||||||
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
|
|
||||||
* Exit Code: -1 <br>
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void crashMinecraft(String errorMessage, Throwable exception)
|
public void crashMinecraft(String errorMessage, Throwable exception)
|
||||||
{
|
{
|
||||||
LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...", exception);
|
LOGGER.fatal(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...", exception);
|
||||||
CrashReport report = new CrashReport(errorMessage, exception);
|
CrashReport report = new CrashReport(errorMessage, exception);
|
||||||
#if MC_VER < MC_1_20_4
|
#if MC_VER < MC_1_20_4
|
||||||
Minecraft.crash(report);
|
Minecraft.crash(report);
|
||||||
#else
|
#else
|
||||||
Minecraft.getInstance().delayCrash(report);
|
MINECRAFT.delayCrash(report);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// mod support //
|
||||||
|
//=============//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getOptionsObject() { return MINECRAFT.options; }
|
public Object getOptionsObject() { return MINECRAFT.options; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// shared //
|
||||||
|
//========//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDedicatedServer() { return false; }
|
public boolean isDedicatedServer() { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getInstallationDirectory() { return MINECRAFT.gameDirectory; }
|
public File getInstallationDirectory() { return MINECRAFT.gameDirectory; }
|
||||||
|
|
||||||
@Override
|
|
||||||
public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPlayerCount()
|
public int getPlayerCount()
|
||||||
{
|
{
|
||||||
@@ -388,4 +331,6 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -28,7 +28,7 @@ import com.mojang.blaze3d.opengl.GlStateManager;
|
|||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ public class MinecraftGLWrapper implements IMinecraftGLWrapper
|
|||||||
{
|
{
|
||||||
public static final MinecraftGLWrapper INSTANCE = new MinecraftGLWrapper();
|
public static final MinecraftGLWrapper INSTANCE = new MinecraftGLWrapper();
|
||||||
|
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+113
-60
@@ -25,9 +25,13 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
import com.mojang.blaze3d.pipeline.RenderTarget;
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||||
import com.mojang.blaze3d.platform.NativeImage;
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
||||||
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
@@ -52,13 +56,19 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWra
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
|
||||||
|
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.Minecraft;
|
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.effect.MobEffects;
|
||||||
|
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
import net.minecraft.tags.FluidTags;
|
import net.minecraft.tags.FluidTags;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
@@ -67,15 +77,17 @@ import org.lwjgl.opengl.GL15;
|
|||||||
#else
|
#else
|
||||||
import net.minecraft.world.level.material.FogType;
|
import net.minecraft.world.level.material.FogType;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.joml.Vector4f;
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_21_5
|
#if MC_VER >= MC_1_21_5
|
||||||
import com.mojang.blaze3d.opengl.GlTexture;
|
import com.mojang.blaze3d.opengl.GlTexture;
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.attribute.EnvironmentAttributes;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton that contains everything
|
* A singleton that contains everything
|
||||||
* related to rendering in Minecraft.
|
* related to rendering in Minecraft.
|
||||||
@@ -84,11 +96,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
{
|
{
|
||||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||||
|
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
private static final Minecraft MC = Minecraft.getInstance();
|
private static final Minecraft MC = Minecraft.getInstance();
|
||||||
|
|
||||||
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
|
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
|
||||||
* Requiring the use of multiple {@link LightMapWrapper}.
|
* Requiring the use of multiple {@link LightMapWrapper}.
|
||||||
@@ -118,12 +128,20 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
@Override
|
@Override
|
||||||
public Vec3f getLookAtVector()
|
public Vec3f getLookAtVector()
|
||||||
{
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
Camera camera = MC.gameRenderer.getMainCamera();
|
Camera camera = MC.gameRenderer.getMainCamera();
|
||||||
return new Vec3f(camera.getLookVector().x(), camera.getLookVector().y(), camera.getLookVector().z());
|
return new Vec3f(camera.getLookVector().x(), camera.getLookVector().y(), camera.getLookVector().z());
|
||||||
|
#else
|
||||||
|
Camera camera = MC.gameRenderer.getMainCamera();
|
||||||
|
return new Vec3f(camera.forwardVector().x(), camera.forwardVector().y(), camera.forwardVector().z());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unless you really need to know if the player is blind,
|
||||||
|
* use {@link MinecraftRenderWrapper#isFogStateSpecial()} or {@link IMinecraftRenderWrapper#isFogStateSpecial()} instead
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
/** Unless you really need to know if the player is blind, use {@link MinecraftRenderWrapper#isFogStateSpecial()}/{@link IMinecraftRenderWrapper#isFogStateSpecial()} instead */
|
|
||||||
public boolean playerHasBlindingEffect()
|
public boolean playerHasBlindingEffect()
|
||||||
{
|
{
|
||||||
if (MC.player == null)
|
if (MC.player == null)
|
||||||
@@ -148,7 +166,11 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
public Vec3d getCameraExactPosition()
|
public Vec3d getCameraExactPosition()
|
||||||
{
|
{
|
||||||
Camera camera = MC.gameRenderer.getMainCamera();
|
Camera camera = MC.gameRenderer.getMainCamera();
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
Vec3 projectedView = camera.getPosition();
|
Vec3 projectedView = camera.getPosition();
|
||||||
|
#else
|
||||||
|
Vec3 projectedView = camera.position();
|
||||||
|
#endif
|
||||||
|
|
||||||
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||||
}
|
}
|
||||||
@@ -182,8 +204,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||||
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||||
);
|
);
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
|
|
||||||
if (mcFogRenderer == null)
|
if (mcFogRenderer == null)
|
||||||
{
|
{
|
||||||
mcFogRenderer = new FogRenderer();
|
mcFogRenderer = new FogRenderer();
|
||||||
@@ -207,9 +228,33 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||||
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||||
);
|
);
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (mcFogRenderer == null)
|
||||||
|
{
|
||||||
|
mcFogRenderer = new FogRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MC.level == null)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return Color.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector4f colorValues = mcFogRenderer.setupFog(
|
||||||
|
MC.gameRenderer.getMainCamera(),
|
||||||
|
MC.options.getEffectiveRenderDistance(),
|
||||||
|
MC.deltaTracker,
|
||||||
|
MC.gameRenderer.getDarkenWorldAmount(MC.deltaTracker.getGameTimeDeltaPartialTick(true)),
|
||||||
|
MC.level);
|
||||||
|
return new Color(
|
||||||
|
Math.max(0f, Math.min(colorValues.x, 1f)), // r
|
||||||
|
Math.max(0f, Math.min(colorValues.y, 1f)), // g
|
||||||
|
Math.max(0f, Math.min(colorValues.z, 1f)), // b
|
||||||
|
Math.max(0f, Math.min(colorValues.w, 1f)) // a
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// getSpecialFogColor() is the same as getFogColor()
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color getSkyColor()
|
public Color getSkyColor()
|
||||||
@@ -221,8 +266,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
frameTime = MC.getFrameTime();
|
frameTime = MC.getFrameTime();
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
frameTime = MC.getTimer().getRealtimeDeltaTicks();
|
frameTime = MC.getTimer().getRealtimeDeltaTicks();
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
frameTime = MC.deltaTracker.getGameTimeDeltaTicks();
|
frameTime = MC.deltaTracker.getGameTimeDeltaTicks();
|
||||||
|
#else
|
||||||
|
frameTime = 0f; // unused
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
@@ -231,9 +278,12 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);
|
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);
|
||||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||||
|
#elif MC_VER <= MC_1_21_10
|
||||||
|
int argbColorInt = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);
|
||||||
|
return ColorUtil.toColorObjARGB(argbColorInt);
|
||||||
#else
|
#else
|
||||||
int argbColorInt = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);;
|
int argbColor = MC.level.environmentAttributes().getValue(EnvironmentAttributes.SKY_COLOR, BlockPos.ZERO);
|
||||||
return ColorUtil.toColorObjARGB(argbColorInt); // TODO MC changed color formats
|
return new Color(ColorUtil.getRed(argbColor), ColorUtil.getGreen(argbColor), ColorUtil.getBlue(argbColor), 255 /* ignore alpha since DH clouds don't render correctly with transparency */);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -243,10 +293,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getFov(float partialTicks)
|
public double getFov(float partialTicks) { return MC.gameRenderer.getFov(MC.gameRenderer.getMainCamera(), partialTicks, true); }
|
||||||
{
|
|
||||||
return MC.gameRenderer.getFov(MC.gameRenderer.getMainCamera(), partialTicks, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Measured in chunks */
|
/** Measured in chunks */
|
||||||
@Override
|
@Override
|
||||||
@@ -260,41 +307,6 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getScreenWidth()
|
|
||||||
{
|
|
||||||
// alternate ways of getting the window's resolution,
|
|
||||||
// using one of these methods may fix the optifine render resolution bug
|
|
||||||
// TODO: test these once we can run with Optifine again
|
|
||||||
// int[] heightArray = new int[1];
|
|
||||||
// int[] widthArray = new int[1];
|
|
||||||
//
|
|
||||||
// long window = GLProxy.getInstance().minecraftGlContext;
|
|
||||||
// GLFW.glfwGetWindowSize(window, widthArray, heightArray); // option 1
|
|
||||||
// GLFW.glfwGetFramebufferSize(window, widthArray, heightArray); // option 2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int width = MC.getWindow().getWidth();
|
|
||||||
if (OPTIFINE_ACCESSOR != null)
|
|
||||||
{
|
|
||||||
// TODO remove comment after testing:
|
|
||||||
// this should fix the issue where different optifine render resolutions screw up the LOD rendering
|
|
||||||
width *= OPTIFINE_ACCESSOR.getRenderResolutionMultiplier();
|
|
||||||
}
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int getScreenHeight()
|
|
||||||
{
|
|
||||||
int height = MC.getWindow().getHeight();
|
|
||||||
if (OPTIFINE_ACCESSOR != null)
|
|
||||||
{
|
|
||||||
height *= OPTIFINE_ACCESSOR.getRenderResolutionMultiplier();
|
|
||||||
}
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -318,7 +330,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBuffer()
|
public int getTargetFramebuffer()
|
||||||
{
|
{
|
||||||
// used so we can access the framebuffer shaders end up rendering to
|
// used so we can access the framebuffer shaders end up rendering to
|
||||||
if (AbstractOptifineAccessor.optifinePresent())
|
if (AbstractOptifineAccessor.optifinePresent())
|
||||||
@@ -399,9 +411,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBufferViewportWidth()
|
public int getTargetFramebufferViewportWidth()
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
return this.getRenderTarget().viewWidth;
|
return this.getRenderTarget().viewWidth;
|
||||||
#else
|
#else
|
||||||
return this.getRenderTarget().width;
|
return this.getRenderTarget().width;
|
||||||
@@ -409,9 +421,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTargetFrameBufferViewportHeight()
|
public int getTargetFramebufferViewportHeight()
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
return this.getRenderTarget().viewHeight;
|
return this.getRenderTarget().viewHeight;
|
||||||
#else
|
#else
|
||||||
return this.getRenderTarget().height;
|
return this.getRenderTarget().height;
|
||||||
@@ -419,7 +431,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ILightMapWrapper getLightmapWrapper(ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
|
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFogStateSpecial()
|
public boolean isFogStateSpecial()
|
||||||
@@ -463,4 +475,45 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
|||||||
wrapper.setLightmapId(tetxureId);
|
wrapper.setLightmapId(tetxureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getShade(EDhDirection lodDirection)
|
||||||
|
{
|
||||||
|
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
|
||||||
|
switch (lodShading)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case AUTO:
|
||||||
|
if (MC.level != null)
|
||||||
|
{
|
||||||
|
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||||
|
return MC.level.getShade(mcDir, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ENABLED:
|
||||||
|
switch (lodDirection)
|
||||||
|
{
|
||||||
|
case DOWN:
|
||||||
|
return 0.5F;
|
||||||
|
default:
|
||||||
|
case UP:
|
||||||
|
return 1.0F;
|
||||||
|
case NORTH:
|
||||||
|
case SOUTH:
|
||||||
|
return 0.8F;
|
||||||
|
case WEST:
|
||||||
|
case EAST:
|
||||||
|
return 0.6F;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DISABLED:
|
||||||
|
return 1.0F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-4
@@ -2,17 +2,20 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||||
import net.minecraft.server.dedicated.DedicatedServer;
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
//@Environment(EnvType.SERVER)
|
|
||||||
public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
||||||
{
|
{
|
||||||
public static final MinecraftServerWrapper INSTANCE = new MinecraftServerWrapper();
|
public static final MinecraftServerWrapper INSTANCE = new MinecraftServerWrapper();
|
||||||
|
|
||||||
|
/** set during server startup */
|
||||||
|
@Nullable
|
||||||
public DedicatedServer dedicatedServer = null;
|
public DedicatedServer dedicatedServer = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
//=============//
|
||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
@@ -33,7 +36,7 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
|||||||
{
|
{
|
||||||
if (this.dedicatedServer == null)
|
if (this.dedicatedServer == null)
|
||||||
{
|
{
|
||||||
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server completed initialization!");
|
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_21_1
|
||||||
@@ -44,9 +47,16 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPlayerCount()
|
public int getPlayerCount()
|
||||||
{
|
{
|
||||||
return this.dedicatedServer.getPlayerCount();
|
if (this.dedicatedServer == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Trying to get player count before dedicated server completed initialization!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.dedicatedServer.getPlayerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
|||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -32,7 +32,7 @@ import java.nio.ByteBuffer;
|
|||||||
public class LightMapWrapper implements ILightMapWrapper
|
public class LightMapWrapper implements ILightMapWrapper
|
||||||
{
|
{
|
||||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
private int textureId = 0;
|
private int textureId = 0;
|
||||||
|
|
||||||
|
|||||||
+61
-101
@@ -2,7 +2,6 @@ package com.seibel.distanthorizons.common.wrappers.world;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache;
|
import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache;
|
||||||
@@ -22,11 +21,11 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWra
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ChunkSource;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -52,9 +51,15 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.attribute.EnvironmentAttributes;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public class ClientLevelWrapper implements IClientLevelWrapper
|
public class ClientLevelWrapper implements IClientLevelWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
/**
|
/**
|
||||||
* weak references are to prevent rare issues
|
* weak references are to prevent rare issues
|
||||||
* where, upon world closure, some levels aren't shutdown/removed properly
|
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||||
@@ -66,17 +71,14 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
private static final Minecraft MINECRAFT = Minecraft.getInstance();
|
||||||
|
|
||||||
private final ClientLevel level;
|
private final ClientLevel level;
|
||||||
private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockCache = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockColorCacheByBlockState = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/** cached method reference to reduce GC overhead */
|
/** cached method reference to reduce GC overhead */
|
||||||
private final Function<BlockState, ClientBlockStateColorCache> cachedBlockColorCacheFunction = (blockState) -> this.createBlockColorCache(blockState);
|
private final Function<BlockState, ClientBlockStateColorCache> createCachedBlockColorCacheFunc = (blockState) -> new ClientBlockStateColorCache(blockState, this);
|
||||||
|
|
||||||
|
|
||||||
private BlockStateWrapper dirtBlockWrapper;
|
private BlockStateWrapper dirtBlockWrapper;
|
||||||
private BlockStateWrapper waterBlockWrapper;
|
private IDhLevel dhLevel;
|
||||||
private BiomeWrapper plainsBiomeWrapper;
|
|
||||||
@Deprecated // TODO circular references are bad
|
|
||||||
private IDhLevel parentDhLevel;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -97,8 +99,13 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
* IE rendering.
|
* IE rendering.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IClientLevelWrapper getWrapperIfDifferent(@Nullable IClientLevelWrapper levelWrapper, @NotNull ClientLevel level)
|
public static IClientLevelWrapper getWrapperIfDifferent(@Nullable IClientLevelWrapper levelWrapper, @NotNull ClientLevel level) // TODO handle null level
|
||||||
{
|
{
|
||||||
|
if (KEYED_CLIENT_LEVEL_MANAGER.isEnabled() && KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel() != levelWrapper)
|
||||||
|
{
|
||||||
|
return getWrapper(level);
|
||||||
|
}
|
||||||
|
|
||||||
ClientLevelWrapper clientLevelWrapper = (ClientLevelWrapper)levelWrapper;
|
ClientLevelWrapper clientLevelWrapper = (ClientLevelWrapper)levelWrapper;
|
||||||
if (clientLevelWrapper == null
|
if (clientLevelWrapper == null
|
||||||
|| clientLevelWrapper.level != level)
|
|| clientLevelWrapper.level != level)
|
||||||
@@ -163,13 +170,17 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// this method only makes sense if we are running a single-player server
|
||||||
|
if (MINECRAFT.getSingleplayerServer() == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Iterable<ServerLevel> serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels();
|
Iterable<ServerLevel> serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels();
|
||||||
|
|
||||||
// attempt to find the server level with the same dimension type
|
// attempt to find the server level with the same dimension type
|
||||||
// TODO this assumes only one level per dimension type, the SubDimensionLevelMatcher will need to be added for supporting multiple levels per dimension
|
// Note: this assumes only one level per dimension type, multiverse servers may not behave correctly
|
||||||
ServerLevelWrapper foundLevelWrapper = null;
|
ServerLevelWrapper foundLevelWrapper = null;
|
||||||
|
|
||||||
// TODO: Surely there is a more efficient way to write this code
|
|
||||||
for (ServerLevel serverLevel : serverLevels)
|
for (ServerLevel serverLevel : serverLevels)
|
||||||
{
|
{
|
||||||
if (serverLevel.dimension() == this.level.dimension())
|
if (serverLevel.dimension() == this.level.dimension())
|
||||||
@@ -195,16 +206,18 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
//====================//
|
//====================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockWrapper)
|
public int getBlockColor(DhBlockPos blockPos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockWrapper)
|
||||||
{
|
{
|
||||||
ClientBlockStateColorCache blockColorCache = this.blockCache.computeIfAbsent(
|
ClientBlockStateColorCache blockColorCache = this.blockColorCacheByBlockState.get(((BlockStateWrapper) blockWrapper).blockState);
|
||||||
((BlockStateWrapper) blockWrapper).blockState,
|
if (blockColorCache == null)
|
||||||
this.cachedBlockColorCacheFunction);
|
{
|
||||||
|
blockColorCache = this.blockColorCacheByBlockState.computeIfAbsent(
|
||||||
|
((BlockStateWrapper) blockWrapper).blockState,
|
||||||
|
this.createCachedBlockColorCacheFunc);
|
||||||
|
}
|
||||||
|
|
||||||
return blockColorCache.getColor((BiomeWrapper) biome, fullDataSource, pos);
|
return blockColorCache.getColor((BiomeWrapper) biome, fullDataSource, blockPos);
|
||||||
}
|
}
|
||||||
/** used by {@link ClientLevelWrapper#cachedBlockColorCacheFunction} */
|
|
||||||
private ClientBlockStateColorCache createBlockColorCache(BlockState block) { return new ClientBlockStateColorCache(block, this); }
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -227,55 +240,28 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
return this.getBlockColor(DhBlockPos.ZERO, BiomeWrapper.EMPTY_WRAPPER, null, this.dirtBlockWrapper);
|
return this.getBlockColor(DhBlockPos.ZERO, BiomeWrapper.EMPTY_WRAPPER, null, this.dirtBlockWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWaterBlockColor()
|
|
||||||
{
|
|
||||||
if (this.waterBlockWrapper == null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.waterBlockWrapper = (BlockStateWrapper) BlockStateWrapper.deserialize(BlockStateWrapper.WATER_RESOURCE_LOCATION_STRING, this);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
// shouldn't happen, but just in case
|
|
||||||
LOGGER.warn("Unable to get water color with resource location ["+BlockStateWrapper.WATER_RESOURCE_LOCATION_STRING+"] with level ["+this+"].", e);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getBlockColor(DhBlockPos.ZERO, BiomeWrapper.EMPTY_WRAPPER, null, this.waterBlockWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearBlockColorCache() { this.blockCache.clear(); }
|
public void clearBlockColorCache() { this.blockColorCacheByBlockState.clear(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBiomeWrapper getPlainsBiomeWrapper()
|
public IDimensionTypeWrapper getDimensionType()
|
||||||
{
|
{
|
||||||
if (this.plainsBiomeWrapper == null)
|
#if MC_VER <= MC_1_21_10
|
||||||
{
|
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType());
|
||||||
try
|
#else
|
||||||
{
|
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName());
|
||||||
this.plainsBiomeWrapper = (BiomeWrapper) BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, this);
|
#endif
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
// shouldn't happen, but just in case
|
|
||||||
LOGGER.warn("Unable to get planes biome with resource location ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"] with level ["+this+"].", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.plainsBiomeWrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
|
public String getDimensionName()
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
@Override
|
return this.level.dimension().location().toString();
|
||||||
public String getDimensionName() { return this.level.dimension().location().toString(); }
|
#else
|
||||||
|
return this.level.dimension().identifier().toString();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; }
|
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; }
|
||||||
@@ -309,37 +295,6 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IChunkWrapper tryGetChunk(DhChunkPos pos)
|
|
||||||
{
|
|
||||||
if (!this.level.hasChunk(pos.getX(), pos.getZ()))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChunkAccess chunk = this.level.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
|
|
||||||
if (chunk == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ChunkWrapper(chunk, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasChunkLoaded(int chunkX, int chunkZ)
|
|
||||||
{
|
|
||||||
ChunkSource source = this.level.getChunkSource();
|
|
||||||
return source.hasChunk(chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockStateWrapper getBlockState(DhBlockPos pos)
|
|
||||||
{ return BlockStateWrapper.fromBlockState(this.level.getBlockState(McObjectConverter.Convert(pos)), this); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBiomeWrapper getBiome(DhBlockPos pos) { return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos)), this); }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientLevel getWrappedMcObject() { return this.level; }
|
public ClientLevel getWrappedMcObject() { return this.level; }
|
||||||
|
|
||||||
@@ -347,18 +302,18 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
public void onUnload()
|
public void onUnload()
|
||||||
{
|
{
|
||||||
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.remove(this.level);
|
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.remove(this.level);
|
||||||
this.parentDhLevel = null;
|
this.dhLevel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getDhSaveFolder()
|
public File getDhSaveFolder()
|
||||||
{
|
{
|
||||||
if (this.parentDhLevel == null)
|
if (this.dhLevel == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parentDhLevel.getSaveStructure().getSaveFolder(this);
|
return this.dhLevel.getSaveStructure().getSaveFolder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -369,17 +324,19 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
//===================//
|
//===================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParentLevel(IDhLevel parentLevel) { this.parentDhLevel = parentLevel; }
|
public void setDhLevel(IDhLevel dhLevel) { this.dhLevel = dhLevel; }
|
||||||
|
@Override
|
||||||
|
public IDhLevel getDhLevel() { return this.dhLevel; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IDhApiCustomRenderRegister getRenderRegister()
|
public IDhApiCustomRenderRegister getRenderRegister()
|
||||||
{
|
{
|
||||||
if (this.parentDhLevel == null)
|
if (this.dhLevel == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parentDhLevel.getGenericRenderer();
|
return this.dhLevel.getGenericRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -388,9 +345,12 @@ public class ClientLevelWrapper implements IClientLevelWrapper
|
|||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
Vec3 colorVec3 = this.level.getCloudColor(tickDelta);
|
Vec3 colorVec3 = this.level.getCloudColor(tickDelta);
|
||||||
return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z);
|
return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z);
|
||||||
#else
|
#elif MC_VER <= MC_1_21_10
|
||||||
int argbColor = this.level.getCloudColor(tickDelta);
|
int argbColor = this.level.getCloudColor(tickDelta);
|
||||||
return ColorUtil.toColorObjARGB(argbColor);
|
return ColorUtil.toColorObjARGB(argbColor);
|
||||||
|
#else
|
||||||
|
int argbColor = this.level.environmentAttributes().getValue(EnvironmentAttributes.CLOUD_COLOR, BlockPos.ZERO);
|
||||||
|
return new Color(ColorUtil.getRed(argbColor), ColorUtil.getGreen(argbColor), ColorUtil.getBlue(argbColor), 255 /* ignore alpha since DH clouds don't render correctly with transparency */);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+44
-19
@@ -26,25 +26,45 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWra
|
|||||||
|
|
||||||
import net.minecraft.world.level.dimension.DimensionType;
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author James Seibel
|
|
||||||
*/
|
|
||||||
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
||||||
{
|
{
|
||||||
private static final ConcurrentMap<String, DimensionTypeWrapper> DIMENSION_WRAPPER_BY_NAME = new ConcurrentHashMap<>();
|
private static final ConcurrentMap<String, DimensionTypeWrapper> DIMENSION_WRAPPER_BY_NAME = new ConcurrentHashMap<>();
|
||||||
private final DimensionType dimensionType;
|
private final DimensionType dimensionType;
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
//=============//
|
||||||
// Constructor //
|
// Constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public DimensionTypeWrapper(DimensionType dimensionType) { this.dimensionType = dimensionType; }
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public DimensionTypeWrapper(DimensionType dimensionType)
|
||||||
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
#else
|
||||||
|
public DimensionTypeWrapper(DimensionType dimensionType, String name)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
String dimName = getName(dimensionType);
|
this.dimensionType = dimensionType;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
this.name = determineName(dimensionType);
|
||||||
|
#else
|
||||||
|
this.name = name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
||||||
|
#else
|
||||||
|
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType, String name)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
String dimName = determineName(dimensionType);
|
||||||
|
#else
|
||||||
|
String dimName = name;
|
||||||
|
#endif
|
||||||
|
|
||||||
// check if the dimension has already been wrapped
|
// check if the dimension has already been wrapped
|
||||||
if (DIMENSION_WRAPPER_BY_NAME.containsKey(dimName)
|
if (DIMENSION_WRAPPER_BY_NAME.containsKey(dimName)
|
||||||
@@ -55,10 +75,26 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
|||||||
|
|
||||||
|
|
||||||
// create the missing wrapper
|
// create the missing wrapper
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
||||||
|
#else
|
||||||
|
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType, dimName);
|
||||||
|
#endif
|
||||||
|
|
||||||
DIMENSION_WRAPPER_BY_NAME.put(dimName, dimensionTypeWrapper);
|
DIMENSION_WRAPPER_BY_NAME.put(dimName, dimensionTypeWrapper);
|
||||||
return dimensionTypeWrapper;
|
return dimensionTypeWrapper;
|
||||||
}
|
}
|
||||||
|
private static String determineName(DimensionType dimensionType)
|
||||||
|
{
|
||||||
|
#if 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
|
||||||
|
return dimensionType.effectsLocation().getPath();
|
||||||
|
#else
|
||||||
|
throw new UnsupportedOperationException("As of MC 1.21.11 the dimension type no longer stores it's name and must be determined from the level.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public static void clearMap() { DIMENSION_WRAPPER_BY_NAME.clear(); }
|
public static void clearMap() { DIMENSION_WRAPPER_BY_NAME.clear(); }
|
||||||
|
|
||||||
@@ -69,16 +105,7 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
|||||||
//=================//
|
//=================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() { return getName(this.dimensionType); }
|
public String getName() { return this.name; }
|
||||||
public static String getName(DimensionType dimensionType)
|
|
||||||
{
|
|
||||||
#if MC_VER <= MC_1_16_5
|
|
||||||
// effectsLocation() is marked as client only, so using the backing field directly
|
|
||||||
return dimensionType.effectsLocation.getPath();
|
|
||||||
#else
|
|
||||||
return dimensionType.effectsLocation().getPath();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasCeiling() { return this.dimensionType.hasCeiling(); }
|
public boolean hasCeiling() { return this.dimensionType.hasCeiling(); }
|
||||||
@@ -89,7 +116,6 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
|||||||
@Override
|
@Override
|
||||||
public Object getWrappedMcObject() { return this.dimensionType; }
|
public Object getWrappedMcObject() { return this.dimensionType; }
|
||||||
|
|
||||||
// there's definitely a better way of doing this, but it should work well enough for now
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); }
|
public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); }
|
||||||
|
|
||||||
@@ -98,7 +124,6 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// base overrides //
|
// base overrides //
|
||||||
//================//
|
//================//
|
||||||
|
|||||||
+95
-69
@@ -24,21 +24,18 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||||
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
import com.seibel.distanthorizons.core.network.messages.base.LevelInitMessage;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.world.EWorldEnvironment;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
@@ -52,16 +49,12 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
|||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
#else
|
import org.jetbrains.annotations.Nullable;
|
||||||
import java.nio.file.Path;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
public class ServerLevelWrapper implements IServerLevelWrapper
|
public class ServerLevelWrapper implements IServerLevelWrapper
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
/**
|
/**
|
||||||
* weak references are to prevent rare issues
|
* weak references are to prevent rare issues
|
||||||
* where, upon world closure, some levels aren't shutdown/removed properly
|
* where, upon world closure, some levels aren't shutdown/removed properly
|
||||||
@@ -69,8 +62,13 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
private static final Map<ServerLevel, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
private static final Map<ServerLevel, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
|
||||||
|
|
||||||
private final ServerLevel level;
|
private final ServerLevel level;
|
||||||
@Deprecated // TODO circular references are bad
|
private IDhLevel dhLevel;
|
||||||
private IDhLevel parentDhLevel;
|
|
||||||
|
/**
|
||||||
|
* this name is cached to prevent issues during shutdown where
|
||||||
|
* the server variables needed may no longer be available.
|
||||||
|
*/
|
||||||
|
private final String KeyedLevelDimensionName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +93,11 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
|
public ServerLevelWrapper(ServerLevel level)
|
||||||
|
{
|
||||||
|
this.level = level;
|
||||||
|
this.KeyedLevelDimensionName = this.createKeyedLevelDimensionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -114,22 +116,80 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getWorldFolderName()
|
public String getKeyedLevelDimensionName() { return this.KeyedLevelDimensionName; }
|
||||||
|
|
||||||
|
private String createKeyedLevelDimensionName()
|
||||||
{
|
{
|
||||||
// Need specifically overworld since it's the only dimension that is stored in a server root folder
|
String dimensionName = this.getDhIdentifier();
|
||||||
|
|
||||||
#if MC_VER >= MC_1_21_3
|
if (Config.Server.sendLevelKeys.get())
|
||||||
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParent().getFileName().toString();
|
{
|
||||||
#else // <= 1.21.3
|
String levelKeyPrefix = Config.Server.levelKeyPrefix.get();
|
||||||
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParentFile().getName();
|
|
||||||
|
if (SharedApi.getEnvironment() == EWorldEnvironment.CLIENT_SERVER)
|
||||||
|
{
|
||||||
|
String cleanWorldFolderName = this.getWorldFolderName()
|
||||||
|
.replaceAll("[^" + LevelInitMessage.ALLOWED_CHARS_REGEX + " ]", "")
|
||||||
|
.replaceAll(" ", "_");
|
||||||
|
|
||||||
|
levelKeyPrefix += (!levelKeyPrefix.isEmpty() ? "_" : "") + cleanWorldFolderName
|
||||||
|
+ "_" + this.getHashedSeedEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (levelKeyPrefix.isEmpty())
|
||||||
|
{
|
||||||
|
levelKeyPrefix = this.getHashedSeedEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
String mainPart = "@" + dimensionName;
|
||||||
|
|
||||||
|
return levelKeyPrefix.substring(0, Math.min(
|
||||||
|
LevelInitMessage.MAX_LENGTH - mainPart.length(),
|
||||||
|
levelKeyPrefix.length()
|
||||||
|
)) + mainPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dimensionName;
|
||||||
|
}
|
||||||
|
private String getWorldFolderName()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
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();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to get world folder name. LODs may not load or save correctly. Error: ["+e.getMessage()+"].", e);
|
||||||
|
return "unknown_world";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DimensionTypeWrapper getDimensionType()
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType());
|
||||||
|
#else
|
||||||
|
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
|
public String getDimensionName()
|
||||||
|
{
|
||||||
@Override
|
#if MC_VER <= MC_1_21_10
|
||||||
public String getDimensionName() { return this.level.dimension().location().toString(); }
|
return this.level.dimension().location().toString();
|
||||||
|
#else
|
||||||
|
return this.level.dimension().identifier().toString();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; }
|
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; }
|
||||||
@@ -163,43 +223,6 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IChunkWrapper tryGetChunk(DhChunkPos pos)
|
|
||||||
{
|
|
||||||
if (!this.level.hasChunk(pos.getX(), pos.getZ()))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChunkAccess chunk = this.level.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FULL, false);
|
|
||||||
if (chunk == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ChunkWrapper(chunk, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasChunkLoaded(int chunkX, int chunkZ)
|
|
||||||
{
|
|
||||||
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
|
|
||||||
ChunkSource source = this.level.getChunkSource();
|
|
||||||
return source.hasChunk(chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBlockStateWrapper getBlockState(DhBlockPos pos)
|
|
||||||
{
|
|
||||||
return BlockStateWrapper.fromBlockState(this.level.getBlockState(McObjectConverter.Convert(pos)), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBiomeWrapper getBiome(DhBlockPos pos)
|
|
||||||
{
|
|
||||||
return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos)), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerLevel getWrappedMcObject() { return this.level; }
|
public ServerLevel getWrappedMcObject() { return this.level; }
|
||||||
|
|
||||||
@@ -208,28 +231,31 @@ public class ServerLevelWrapper implements IServerLevelWrapper
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setParentLevel(IDhLevel parentLevel) { this.parentDhLevel = parentLevel; }
|
public void setDhLevel(IDhLevel dhLevel) { this.dhLevel = dhLevel; }
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public IDhLevel getDhLevel() { return this.dhLevel; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IDhApiCustomRenderRegister getRenderRegister()
|
public IDhApiCustomRenderRegister getRenderRegister()
|
||||||
{
|
{
|
||||||
if (this.parentDhLevel == null)
|
if (this.dhLevel == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parentDhLevel.getGenericRenderer();
|
return this.dhLevel.getGenericRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getDhSaveFolder()
|
public File getDhSaveFolder()
|
||||||
{
|
{
|
||||||
if (this.parentDhLevel == null)
|
if (this.dhLevel == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.parentDhLevel.getSaveStructure().getSaveFolder(this);
|
return this.dhLevel.getSaveStructure().getSaveFolder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+389
-884
File diff suppressed because it is too large
Load Diff
+92
@@ -0,0 +1,92 @@
|
|||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Spliterator;
|
||||||
|
import java.util.Spliterators;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
public class ChunkPosGenStream
|
||||||
|
{
|
||||||
|
|
||||||
|
public static Iterator<ChunkPos> getIterator(int genMinX, int genMinZ, int width, int extraRadius)
|
||||||
|
{ return getStream(genMinX, genMinZ, width, extraRadius).iterator(); }
|
||||||
|
/** @param extraRadius in both the positive and negative directions */
|
||||||
|
public static Stream<ChunkPos> getStream(int genMinX, int genMinZ, int width, int extraRadius)
|
||||||
|
{ return StreamSupport.stream(new InclusiveChunkPosIterator(genMinX, genMinZ, width, extraRadius), false); }
|
||||||
|
|
||||||
|
private static class InclusiveChunkPosIterator extends Spliterators.AbstractSpliterator<ChunkPos>
|
||||||
|
{
|
||||||
|
private final int minX;
|
||||||
|
private final int minZ;
|
||||||
|
|
||||||
|
private final int maxX;
|
||||||
|
private final int maxZ;
|
||||||
|
|
||||||
|
|
||||||
|
/** current X pos */
|
||||||
|
int x;
|
||||||
|
/** current Z pos */
|
||||||
|
private int z;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
protected InclusiveChunkPosIterator(int genMinX, int genMinZ, int width, int extraRadius)
|
||||||
|
{
|
||||||
|
super(getCount(width, extraRadius), Spliterator.SIZED);
|
||||||
|
|
||||||
|
this.minX = genMinX - extraRadius;
|
||||||
|
this.minZ = genMinZ - extraRadius;
|
||||||
|
|
||||||
|
this.maxX = genMinX + (width - 1) + extraRadius;
|
||||||
|
this.maxZ = genMinZ + (width - 1) + extraRadius;
|
||||||
|
|
||||||
|
// X starts at 1 minus the minX so we can immediately re-add 1 in the tryAdvance() loop
|
||||||
|
this.x = this.minX - 1;
|
||||||
|
this.z = this.minZ;
|
||||||
|
}
|
||||||
|
private static int getCount(int width, int extraRadius)
|
||||||
|
{
|
||||||
|
int widthPlusExtra = width + (extraRadius * 2);
|
||||||
|
return widthPlusExtra * widthPlusExtra;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================//
|
||||||
|
// iterator method //
|
||||||
|
//=================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryAdvance(Consumer<? super ChunkPos> consumer)
|
||||||
|
{
|
||||||
|
if (this.x == this.maxX && this.z == this.maxZ)
|
||||||
|
{
|
||||||
|
// the last returned position was the final valid position
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.x == this.maxX)
|
||||||
|
{
|
||||||
|
// we reached the max X position, loop back around in the next Z row
|
||||||
|
this.x = this.minX;
|
||||||
|
this.z++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
consumer.accept(new ChunkPos(this.x, this.z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+74
-91
@@ -19,114 +19,118 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
|
||||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
|
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
|
||||||
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.ExceptionUtil;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.util.objects.EventTimer;
|
|
||||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
public final class GenerationEvent
|
public final class GenerationEvent
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();;
|
||||||
private static int generationFutureDebugIDs = 0;
|
|
||||||
|
|
||||||
|
private static final AtomicInteger DEBUG_ID_REF = new AtomicInteger(0);
|
||||||
|
|
||||||
|
|
||||||
|
/** can be used for troubleshooting */
|
||||||
public final int id;
|
public final int id;
|
||||||
public final ThreadedParameters threadedParam;
|
|
||||||
|
public final ThreadWorldGenParams threadedParam;
|
||||||
public final DhChunkPos minPos;
|
public final DhChunkPos minPos;
|
||||||
/** the number of chunks wide this event is */
|
public final int widthInChunks;
|
||||||
public final int size;
|
|
||||||
public final EDhApiWorldGenerationStep targetGenerationStep;
|
public final EDhApiWorldGenerationStep targetGenerationStep;
|
||||||
public final EDhApiDistantGeneratorMode generatorMode;
|
public final EDhApiDistantGeneratorMode generatorMode;
|
||||||
public EventTimer timer = null;
|
public final CompletableFuture<Void> future;
|
||||||
public long inQueueTime;
|
|
||||||
public long timeoutTime = -1;
|
|
||||||
public CompletableFuture<Void> future = null;
|
|
||||||
public final Consumer<IChunkWrapper> resultConsumer;
|
public final Consumer<IChunkWrapper> resultConsumer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public GenerationEvent(
|
//=============//
|
||||||
DhChunkPos minPos, int size, BatchGenerationEnvironment generationGroup,
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
private GenerationEvent(
|
||||||
|
DhChunkPos minPos, int widthInChunks, BatchGenerationEnvironment generationGroup,
|
||||||
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep targetGenerationStep, Consumer<IChunkWrapper> resultConsumer)
|
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep targetGenerationStep, Consumer<IChunkWrapper> resultConsumer)
|
||||||
{
|
{
|
||||||
this.inQueueTime = System.nanoTime();
|
this.id = DEBUG_ID_REF.getAndIncrement();
|
||||||
this.id = generationFutureDebugIDs++;
|
|
||||||
this.minPos = minPos;
|
this.minPos = minPos;
|
||||||
this.size = size;
|
this.widthInChunks = widthInChunks;
|
||||||
this.generatorMode = generatorMode;
|
|
||||||
this.targetGenerationStep = targetGenerationStep;
|
this.targetGenerationStep = targetGenerationStep;
|
||||||
this.threadedParam = ThreadedParameters.getOrMake(generationGroup.params);
|
this.generatorMode = generatorMode;
|
||||||
|
this.threadedParam = ThreadWorldGenParams.getOrMake(generationGroup.globalParams);
|
||||||
|
this.future = new CompletableFuture<>();
|
||||||
this.resultConsumer = resultConsumer;
|
this.resultConsumer = resultConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static GenerationEvent startEvent(
|
//=======//
|
||||||
DhChunkPos minPos, int size, BatchGenerationEnvironment genEnvironment,
|
// start //
|
||||||
|
//=======//
|
||||||
|
|
||||||
|
public static GenerationEvent start(
|
||||||
|
DhChunkPos minPos, int widthInChunks, BatchGenerationEnvironment genEnvironment,
|
||||||
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep target, Consumer<IChunkWrapper> resultConsumer,
|
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep target, Consumer<IChunkWrapper> resultConsumer,
|
||||||
ExecutorService worldGeneratorThreadPool)
|
ExecutorService worldGeneratorThreadPool)
|
||||||
{
|
{
|
||||||
GenerationEvent generationEvent = new GenerationEvent(minPos, size, genEnvironment, generatorMode, target, resultConsumer);
|
GenerationEvent genEvent = new GenerationEvent(minPos, widthInChunks, genEnvironment, generatorMode, target, resultConsumer);
|
||||||
generationEvent.future = CompletableFuture.supplyAsync(() ->
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
long runStartTime = System.nanoTime();
|
worldGeneratorThreadPool.execute(() ->
|
||||||
generationEvent.timeoutTime = runStartTime;
|
|
||||||
generationEvent.inQueueTime = runStartTime - generationEvent.inQueueTime;
|
|
||||||
generationEvent.timer = new EventTimer("setup");
|
|
||||||
|
|
||||||
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
genEnvironment.generateLodFromListAsync(generationEvent, (runnable) ->
|
try
|
||||||
{
|
{
|
||||||
worldGeneratorThreadPool.execute(() ->
|
BatchGenerationEnvironment.isDhWorldGenThreadRef.set(true);
|
||||||
|
|
||||||
|
|
||||||
|
if (genEvent.generatorMode == EDhApiDistantGeneratorMode.INTERNAL_SERVER)
|
||||||
|
{
|
||||||
|
genEnvironment.internalServerGenerator.generateChunksViaInternalServer(genEvent);
|
||||||
|
genEvent.future.complete(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
boolean alreadyMarked = BatchGenerationEnvironment.isCurrentThreadDistantGeneratorThread();
|
|
||||||
if (!alreadyMarked)
|
|
||||||
{
|
|
||||||
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
runnable.run();
|
genEnvironment.generateEvent(genEvent);
|
||||||
}
|
}
|
||||||
catch (Throwable throwable)
|
catch (Throwable throwable)
|
||||||
{
|
{
|
||||||
handleWorldGenThrowable(generationEvent, throwable);
|
handleWorldGenThrowable(genEvent, throwable);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (!alreadyMarked)
|
genEvent.future.complete(null);
|
||||||
{
|
|
||||||
BatchGenerationEnvironment.isDistantGeneratorThread.set(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
}
|
||||||
}
|
catch (Throwable initialThrowable)
|
||||||
catch (Throwable initialThrowable)
|
{
|
||||||
{
|
handleWorldGenThrowable(genEvent, initialThrowable);
|
||||||
handleWorldGenThrowable(generationEvent, initialThrowable);
|
}
|
||||||
}
|
finally
|
||||||
finally
|
{
|
||||||
{
|
BatchGenerationEnvironment.isDhWorldGenThreadRef.remove();
|
||||||
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
return null;
|
catch (RejectedExecutionException e)
|
||||||
}, worldGeneratorThreadPool);
|
{
|
||||||
return generationEvent;
|
genEvent.future.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return genEvent;
|
||||||
}
|
}
|
||||||
/** There's probably a better way to handle this, but it'll work for now */
|
/** There's probably a better way to handle this, but it'll work for now */
|
||||||
private static void handleWorldGenThrowable(GenerationEvent generationEvent, Throwable initialThrowable)
|
private static void handleWorldGenThrowable(GenerationEvent generationEvent, Throwable initialThrowable)
|
||||||
@@ -137,9 +141,8 @@ public final class GenerationEvent
|
|||||||
throwable = throwable.getCause();
|
throwable = throwable.getCause();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (throwable instanceof InterruptedException
|
boolean isShutdownException = ExceptionUtil.isShutdownException(throwable);
|
||||||
|| throwable instanceof UncheckedInterruptedException
|
if (isShutdownException)
|
||||||
|| throwable instanceof RejectedExecutionException)
|
|
||||||
{
|
{
|
||||||
// these exceptions can be ignored, generally they just mean
|
// these exceptions can be ignored, generally they just mean
|
||||||
// the thread is busy so it'll need to try again later.
|
// the thread is busy so it'll need to try again later.
|
||||||
@@ -154,35 +157,15 @@ public final class GenerationEvent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isComplete() { return this.future.isDone(); }
|
|
||||||
|
|
||||||
public boolean hasTimeout(int duration, TimeUnit unit)
|
|
||||||
{
|
|
||||||
if (this.timeoutTime == -1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long currentTime = System.nanoTime();
|
|
||||||
long delta = currentTime - this.timeoutTime;
|
|
||||||
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean terminate()
|
//================//
|
||||||
{
|
// base overrides //
|
||||||
LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
//================//
|
||||||
ThreadPoolUtil.WORLD_GEN_THREAD_FACTORY.dumpAllThreadStacks();
|
|
||||||
this.future.cancel(true);
|
|
||||||
return this.future.isCancelled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshTimeout()
|
|
||||||
{
|
|
||||||
this.timeoutTime = System.nanoTime();
|
|
||||||
UncheckedInterruptedException.throwIfInterrupted();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return this.id + ":" + this.size + "@" + this.minPos + "(" + this.targetGenerationStep + ")"; }
|
public String toString() { return this.id + ":" + this.widthInChunks + "@" + this.minPos + "(" + this.targetGenerationStep + ")"; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+311
@@ -0,0 +1,311 @@
|
|||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.DhApi;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
|
import com.seibel.distanthorizons.core.enums.EMinecraftColor;
|
||||||
|
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;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IC2meAccessor;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
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;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class InternalServerGenerator
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.name("LOD World Gen - Internal Server")
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logWorldGenEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final DhLogger CHUNK_LOAD_LOGGER = new DhLoggerBuilder()
|
||||||
|
.name("LOD Chunk Loading")
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logWorldGenChunkLoadEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static final IC2meAccessor C2ME_ACCESSOR = ModAccessorInjector.INSTANCE.get(IC2meAccessor.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to revert the ignore logic in {@link SharedApi} so
|
||||||
|
* that a given chunk pos can be handled again.
|
||||||
|
* A timer is used so we don't have to inject into MC's code and it works sell enough
|
||||||
|
* most of the time.
|
||||||
|
* If a chunk does get through due the timeout not being long enough that isn't the end of the world.
|
||||||
|
*/
|
||||||
|
private static final int MS_TO_IGNORE_CHUNK_AFTER_COMPLETION = 5_000;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
private static final TicketType<ChunkPos> 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);
|
||||||
|
#else
|
||||||
|
private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* flags */TicketType.FLAG_LOADING);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private static boolean c2meMissingWarningLogged = false;
|
||||||
|
|
||||||
|
|
||||||
|
private final GlobalWorldGenParams params;
|
||||||
|
private final IDhServerLevel dhServerLevel;
|
||||||
|
private final Timer chunkSaveIgnoreTimer = TimerUtil.CreateTimer("ChunkSaveIgnoreTimer");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public InternalServerGenerator(GlobalWorldGenParams params, IDhServerLevel dhServerLevel)
|
||||||
|
{
|
||||||
|
this.params = params;
|
||||||
|
this.dhServerLevel = dhServerLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// generation //
|
||||||
|
//============//
|
||||||
|
|
||||||
|
public void generateChunksViaInternalServer(GenerationEvent genEvent)
|
||||||
|
{
|
||||||
|
this.runValidation();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//=====================//
|
||||||
|
// create gen requests //
|
||||||
|
//=====================//
|
||||||
|
|
||||||
|
ArrayList<CompletableFuture<ChunkAccess>> getChunkFutureList = new ArrayList<>();
|
||||||
|
{
|
||||||
|
Iterator<ChunkPos> chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0);
|
||||||
|
while (chunkPosIterator.hasNext())
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = chunkPosIterator.next();
|
||||||
|
|
||||||
|
CompletableFuture<ChunkAccess> requestChunkFuture =
|
||||||
|
this.requestChunkFromServerAsync(chunkPos)
|
||||||
|
// log errors if necessary
|
||||||
|
.whenCompleteAsync(
|
||||||
|
(chunk, throwable) ->
|
||||||
|
{
|
||||||
|
// unwrap the CompletionException if necessary
|
||||||
|
Throwable actualThrowable = throwable;
|
||||||
|
while (actualThrowable instanceof CompletionException)
|
||||||
|
{
|
||||||
|
actualThrowable = actualThrowable.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualThrowable != null)
|
||||||
|
{
|
||||||
|
// ignore expected shutdown exceptions
|
||||||
|
boolean isShutdownException =
|
||||||
|
ExceptionUtil.isShutdownException(actualThrowable)
|
||||||
|
|| actualThrowable.getMessage().contains("Unloaded chunk");
|
||||||
|
if (!isShutdownException)
|
||||||
|
{
|
||||||
|
CHUNK_LOAD_LOGGER.warn("DistantHorizons: Couldn't load chunk [" + chunkPos + "] from server, error: [" + actualThrowable.getMessage() + "].", actualThrowable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getChunkFutureList.add(requestChunkFuture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============================//
|
||||||
|
// wait for generation requests //
|
||||||
|
//==============================//
|
||||||
|
|
||||||
|
// Join-ing each thread will prevent DH from working on anything else
|
||||||
|
// but will also prevent over-queuing world gen tasks.
|
||||||
|
// If C2ME is present the CPU will still be well utilized.
|
||||||
|
|
||||||
|
ArrayList<IChunkWrapper> chunkWrappers = new ArrayList<>();
|
||||||
|
for (int i = 0; i < getChunkFutureList.size(); i++)
|
||||||
|
{
|
||||||
|
CompletableFuture<ChunkAccess> getChunkFuture = getChunkFutureList.get(i);
|
||||||
|
ChunkAccess chunk = getChunkFuture.join();
|
||||||
|
if (chunk != null)
|
||||||
|
{
|
||||||
|
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper());
|
||||||
|
chunkWrapper.createDhHeightMaps();
|
||||||
|
chunkWrappers.add(chunkWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========================//
|
||||||
|
// process generated chunks //
|
||||||
|
//==========================//
|
||||||
|
|
||||||
|
int maxSkyLight = this.dhServerLevel.getServerLevelWrapper().hasSkyLight() ? LodUtil.MAX_MC_LIGHT : LodUtil.MIN_MC_LIGHT;
|
||||||
|
for (int i = 0; i < chunkWrappers.size(); i++)
|
||||||
|
{
|
||||||
|
ChunkWrapper chunkWrapper = (ChunkWrapper)chunkWrappers.get(i);
|
||||||
|
|
||||||
|
// pre-generated chunks should have lighting but new ones won't
|
||||||
|
if (!chunkWrapper.isDhBlockLightingCorrect())
|
||||||
|
{
|
||||||
|
DhLightingEngine.INSTANCE.bakeChunkBlockLighting(chunkWrapper, chunkWrappers, maxSkyLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dhServerLevel.updateBeaconBeamsForChunk(chunkWrapper, chunkWrappers);
|
||||||
|
genEvent.resultConsumer.accept(chunkWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// release all chunks from the server to prevent out of memory issues
|
||||||
|
Iterator<ChunkPos> chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0);
|
||||||
|
while (chunkPosIterator.hasNext())
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = chunkPosIterator.next();
|
||||||
|
this.releaseChunkFromServer(this.params.mcServerLevel, chunkPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void runValidation()
|
||||||
|
{
|
||||||
|
// DH thread check
|
||||||
|
if (!DhApi.isDhThread()
|
||||||
|
&& ModInfo.IS_DEV_BUILD)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Internal server generation should be called from one of DH's world gen thread. Current thread: ["+Thread.currentThread().getName()+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// C2ME present?
|
||||||
|
if (C2ME_ACCESSOR == null
|
||||||
|
&& !c2meMissingWarningLogged)
|
||||||
|
{
|
||||||
|
c2meMissingWarningLogged = true;
|
||||||
|
|
||||||
|
String c2meWarning = "C2ME missing, \n" +
|
||||||
|
"low CPU usage and slow world gen speeds expected. \n" +
|
||||||
|
"DH is set to use MC's internal server for world gen \n" +
|
||||||
|
"this mode is less efficient unless a mod like C2ME is present."
|
||||||
|
;
|
||||||
|
|
||||||
|
if (Config.Common.Logging.Warning.showSlowWorldGenSettingWarnings.get())
|
||||||
|
{
|
||||||
|
String message =
|
||||||
|
EMinecraftColor.ORANGE + "Distant Horizons: slow world gen." + EMinecraftColor.CLEAR_FORMATTING + "\n" +
|
||||||
|
c2meWarning;
|
||||||
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.warn(c2meWarning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private CompletableFuture<ChunkAccess> requestChunkFromServerAsync(ChunkPos chunkPos)
|
||||||
|
{
|
||||||
|
return CompletableFuture.supplyAsync(() ->
|
||||||
|
{
|
||||||
|
ServerLevel level = this.params.mcServerLevel;
|
||||||
|
|
||||||
|
// ignore chunk update events for this position
|
||||||
|
SharedApi.CHUNK_UPDATE_QUEUE_MANAGER.addPosToIgnore(new DhChunkPos(chunkPos.x, chunkPos.z));
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
int chunkLevel = 33; // 33 is equivalent to FULL Chunk
|
||||||
|
level.getChunkSource().distanceManager.addTicket(DH_SERVER_GEN_TICKET, chunkPos, chunkLevel, chunkPos);
|
||||||
|
#else
|
||||||
|
level.getChunkSource().addTicketWithRadius(DH_SERVER_GEN_TICKET, chunkPos, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// probably not the most optimal to run updates here, but fast enough
|
||||||
|
level.getChunkSource().distanceManager.runAllUpdates(level.getChunkSource().chunkMap);
|
||||||
|
|
||||||
|
ChunkHolder chunkHolder = level.getChunkSource().chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong());
|
||||||
|
if (chunkHolder == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("No chunk chunkHolder for pos ["+chunkPos+"] after ticket has been added.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_4
|
||||||
|
return chunkHolder.getOrScheduleFuture(ChunkStatus.FEATURES, level.getChunkSource().chunkMap)
|
||||||
|
.thenApply(result -> result.left().orElseThrow(() -> new RuntimeException(result.right().get().toString()))); // can throw if the server is shutting down
|
||||||
|
#elif MC_VER <= MC_1_20_6
|
||||||
|
return chunkHolder.getOrScheduleFuture(ChunkStatus.FEATURES, level.getChunkSource().chunkMap)
|
||||||
|
.thenApply(result -> result.orElseThrow(() -> new RuntimeException(result.toString()))); // can throw if the server is shutting down
|
||||||
|
#else
|
||||||
|
return chunkHolder.scheduleChunkGenerationTask(ChunkStatus.FEATURES, level.getChunkSource().chunkMap)
|
||||||
|
.thenApply(result -> result.orElseThrow(() -> new RuntimeException(result.getError()))); // can throw if the server is shutting down
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}, this.params.mcServerLevel.getChunkSource().chunkMap.mainThreadExecutor)
|
||||||
|
.thenCompose(Function.identity());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* mitigates out of memory issues in the vanilla chunk system. <br>
|
||||||
|
* See: https://github.com/pop4959/Chunky/pull/383
|
||||||
|
*/
|
||||||
|
private void releaseChunkFromServer(ServerLevel level, ChunkPos chunkPos)
|
||||||
|
{
|
||||||
|
level.getChunkSource().chunkMap.mainThreadExecutor.execute(() ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if 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
|
||||||
|
|
||||||
|
level.getChunkSource().chunkMap.tick(() -> false);
|
||||||
|
|
||||||
|
#if MC_VER > MC_1_16_5
|
||||||
|
level.entityManager.tick();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// give MC a few seconds to save the chunk before
|
||||||
|
// we can process update events there again
|
||||||
|
this.chunkSaveIgnoreTimer.schedule(new TimerTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run() { SharedApi.CHUNK_UPDATE_QUEUE_MANAGER.removePosToIgnore(new DhChunkPos(chunkPos.x, chunkPos.z)); }
|
||||||
|
}, MS_TO_IGNORE_CHUNK_AFTER_COMPLETION);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Failed to release chunk back to internal server. Error: ["+e.getMessage()+"]", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
-109
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment.PerfCalculator;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager;
|
|
||||||
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.level.WorldGenLevel;
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public final class ThreadedParameters
|
|
||||||
{
|
|
||||||
private static final ThreadLocal<ThreadedParameters> LOCAL_PARAM = new ThreadLocal<>();
|
|
||||||
|
|
||||||
final ServerLevel level;
|
|
||||||
public WorldGenStructFeatManager structFeat = null;
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
public StructureCheck structCheck;
|
|
||||||
#endif
|
|
||||||
boolean isValid = true;
|
|
||||||
public final PerfCalculator perf = new PerfCalculator();
|
|
||||||
|
|
||||||
private static GlobalParameters previousGlobalParameters = null;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static ThreadedParameters getOrMake(GlobalParameters param)
|
|
||||||
{
|
|
||||||
ThreadedParameters tParam = LOCAL_PARAM.get();
|
|
||||||
if (tParam != null && tParam.isValid && tParam.level == param.level)
|
|
||||||
{
|
|
||||||
return tParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
tParam = new ThreadedParameters(param);
|
|
||||||
LOCAL_PARAM.set(tParam);
|
|
||||||
return tParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ThreadedParameters(GlobalParameters param)
|
|
||||||
{
|
|
||||||
previousGlobalParameters = param;
|
|
||||||
|
|
||||||
this.level = param.level;
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, level);
|
|
||||||
#elif MC_VER < MC_1_19_2
|
|
||||||
this.structCheck = this.createStructureCheck(param);
|
|
||||||
#else
|
|
||||||
this.structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
|
||||||
param.level.dimension(), param.generator, param.randomState, level, param.generator.getBiomeSource(), param.worldSeed,
|
|
||||||
param.fixerUpper);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void markAsInvalid() { isValid = false; }
|
|
||||||
|
|
||||||
public void makeStructFeat(WorldGenLevel genLevel, GlobalParameters param)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_19_4
|
|
||||||
structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel #if MC_VER >= MC_1_18_2 , structCheck #endif );
|
|
||||||
#else
|
|
||||||
structFeat = new WorldGenStructFeatManager(param.worldOptions, genLevel, structCheck);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2 && MC_VER < MC_1_19_2
|
|
||||||
public void recreateStructureCheck()
|
|
||||||
{
|
|
||||||
if (previousGlobalParameters != null)
|
|
||||||
{
|
|
||||||
this.structCheck = createStructureCheck(previousGlobalParameters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private StructureCheck createStructureCheck(GlobalParameters param)
|
|
||||||
{
|
|
||||||
return new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
|
||||||
param.level.dimension(), param.generator, this.level, param.generator.getBiomeSource(), param.worldSeed,
|
|
||||||
param.fixerUpper);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public void recreateStructureCheck() { /* do nothing */ }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
+745
@@ -0,0 +1,745 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU GPL 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 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
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.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
#if MC_VER >= MC_1_19_4
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.NbtOps;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.world.level.*;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.Biomes;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.*;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_9
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
|
#endif
|
||||||
|
import net.minecraft.world.ticks.LevelChunkTicks;
|
||||||
|
#endif
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER == MC_1_20_6
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkType;
|
||||||
|
#elif MC_VER >= MC_1_21_1
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
|
||||||
|
|
||||||
|
public class ChunkCompoundTagParser
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.name("LOD Chunk Reader")
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logWorldGenChunkLoadEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static final AtomicBoolean ZERO_CHUNK_POS_ERROR_LOGGED_REF = new AtomicBoolean(false);
|
||||||
|
private static final ConcurrentHashMap<String, Object> LOGGED_ERROR_MESSAGE_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static boolean lightingSectionErrorLogged = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// read chunk //
|
||||||
|
//============//
|
||||||
|
|
||||||
|
public static ChunkWrapper createFromTag(
|
||||||
|
WorldGenLevel mcWorldGenLevel, IDhServerLevel dhServerLevel,
|
||||||
|
ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
CompoundTag tagLevel = chunkData.getCompound("Level");
|
||||||
|
#else
|
||||||
|
CompoundTag tagLevel = chunkData;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================//
|
||||||
|
// validate the chunkPos //
|
||||||
|
//=======================//
|
||||||
|
|
||||||
|
int chunkX = CompoundTagUtil.getInt(tagLevel,"xPos");
|
||||||
|
int chunkZ = CompoundTagUtil.getInt(tagLevel, "zPos");
|
||||||
|
ChunkPos actualChunkPos = new ChunkPos(chunkX, chunkZ);
|
||||||
|
|
||||||
|
// confirm chunk pos is correct
|
||||||
|
if (!Objects.equals(chunkPos, actualChunkPos))
|
||||||
|
{
|
||||||
|
if (chunkX == 0 && chunkZ == 0)
|
||||||
|
{
|
||||||
|
if (!ZERO_CHUNK_POS_ERROR_LOGGED_REF.getAndSet(true))
|
||||||
|
{
|
||||||
|
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
||||||
|
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
||||||
|
"This might happen if the world was created using an external program. \n" +
|
||||||
|
"DH will attempt to parse the chunk anyway and won't log this message again.\n" +
|
||||||
|
"If issues arise please try optimizing your world to fix this issue. \n" +
|
||||||
|
"World optimization can be done from the singleplayer world selection screen." +
|
||||||
|
" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.error("Chunk file at ["+chunkPos.toString()+"] is in the wrong location. \n" +
|
||||||
|
"Please try optimizing your world to fix this issue. \n" +
|
||||||
|
"World optimization can be done from the singleplayer world selection screen. \n" +
|
||||||
|
"(Expected pos: ["+chunkPos.toString()+"], actual ["+actualChunkPos.toString()+"])" +
|
||||||
|
" ");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// get ticks //
|
||||||
|
//===========//
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
||||||
|
mcWorldGenLevel.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), #if MC_VER >= MC_1_17_1 mcWorldGenLevel, #endif
|
||||||
|
chunkPos, mcWorldGenLevel.getLevel().getChunkSource().getGenerator().getBiomeSource(),
|
||||||
|
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
|
||||||
|
|
||||||
|
String BLOCK_TICKS_TAG_PRE18 = "TileTicks";
|
||||||
|
TickList<Block> blockTicks = tagLevel.contains(BLOCK_TICKS_TAG_PRE18, 9)
|
||||||
|
? ChunkTickList.create(tagLevel.getList(BLOCK_TICKS_TAG_PRE18, 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
|
||||||
|
: new ProtoTickList<Block>(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
|
||||||
|
tagLevel.getList("ToBeTicked", 9) #if MC_VER >= MC_1_17_1 , mcWorldGenLevel #endif );
|
||||||
|
|
||||||
|
String FLUID_TICKS_TAG_PRE18 = "LiquidTicks";
|
||||||
|
TickList<Fluid> fluidTicks = tagLevel.contains(FLUID_TICKS_TAG_PRE18, 9)
|
||||||
|
? ChunkTickList.create(tagLevel.getList(FLUID_TICKS_TAG_PRE18, 10), Registry.FLUID::getKey, Registry.FLUID::get)
|
||||||
|
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
||||||
|
tagLevel.getList("LiquidsToBeTicked", 9) #if MC_VER >= MC_1_17_1 , mcWorldGenLevel #endif );
|
||||||
|
#else
|
||||||
|
// ticks shouldn't be needed so ignore them for MC versions after 1.18.2
|
||||||
|
LevelChunkTicks<Block> blockTicks = new LevelChunkTicks<>();
|
||||||
|
LevelChunkTicks<Fluid> fluidTicks = new LevelChunkTicks<>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====================//
|
||||||
|
// get misc properties //
|
||||||
|
//=====================//
|
||||||
|
|
||||||
|
int sectionYCount = #if MC_VER < MC_1_17_1 16; #else mcWorldGenLevel.getSectionsCount(); #endif
|
||||||
|
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYCount];
|
||||||
|
boolean hasBlocks = readAndPopulateSections(mcWorldGenLevel, chunkPos, tagLevel, chunkSections);
|
||||||
|
if (!hasBlocks)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long inhabitedTime = CompoundTagUtil.getLong(tagLevel, "InhabitedTime");
|
||||||
|
boolean isLightOn = CompoundTagUtil.getBoolean(tagLevel, "isLightOn");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// make chunk //
|
||||||
|
//============//
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
LevelChunk chunk = new LevelChunk((Level) mcWorldGenLevel.getLevel(), chunkPos, chunkBiomeContainer, UpgradeData.EMPTY, blockTicks,
|
||||||
|
fluidTicks, inhabitedTime, chunkSections, null);
|
||||||
|
#else
|
||||||
|
LevelChunk chunk = new LevelChunk((Level) mcWorldGenLevel, chunkPos, UpgradeData.EMPTY, blockTicks,
|
||||||
|
fluidTicks, inhabitedTime, chunkSections, null, null);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set some states after object creation
|
||||||
|
chunk.setLightCorrect(isLightOn);
|
||||||
|
boolean hasHeightmapData = readHeightmaps(chunk, chunkData);
|
||||||
|
|
||||||
|
// chunk wrapper so we can pass along extra data more easily
|
||||||
|
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, dhServerLevel.getServerLevelWrapper());
|
||||||
|
chunkWrapper.createDhHeightMaps();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================//
|
||||||
|
// check if chunk has blocks //
|
||||||
|
//===========================//
|
||||||
|
|
||||||
|
// in some MC versions all the NBT data will be there
|
||||||
|
// but the chunk will be totally empty,
|
||||||
|
// usually this means the chunk was only partially generated.
|
||||||
|
// If that happens we should try to generate the chunk from scratch
|
||||||
|
// otherwise we can end up with large empty holes in the world.
|
||||||
|
|
||||||
|
// walking through the heightmap (recreated by DH if missing)
|
||||||
|
// is a fast way to check if there are any blocks in the chunk
|
||||||
|
boolean chunkHasBlocks = false;
|
||||||
|
int serverMinHeight = dhServerLevel.getServerLevelWrapper().getMinHeight();
|
||||||
|
for (int x = 0; x < 16 && !chunkHasBlocks; x++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < 16 && !chunkHasBlocks; z++)
|
||||||
|
{
|
||||||
|
int heightMap = Math.max(
|
||||||
|
// max between both heightmaps just in case there's a discrepancy
|
||||||
|
chunkWrapper.getLightBlockingHeightMapValue(x, z),
|
||||||
|
chunkWrapper.getSolidHeightMapValue(x, z)
|
||||||
|
);
|
||||||
|
if (heightMap != serverMinHeight)
|
||||||
|
{
|
||||||
|
chunkHasBlocks = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (chunkHasBlocks)
|
||||||
|
{
|
||||||
|
return chunkWrapper;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no blocks detected, this chunk should be generated from scratch
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================//
|
||||||
|
// chunk sections //
|
||||||
|
// (Blocks/biomes) //
|
||||||
|
//=================//
|
||||||
|
|
||||||
|
/** handles both blocks and biomes */
|
||||||
|
private static boolean readAndPopulateSections(
|
||||||
|
LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData,
|
||||||
|
LevelChunkSection[] chunkSections)
|
||||||
|
{
|
||||||
|
int sectionYCount = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
||||||
|
|
||||||
|
ListTag tagSections = CompoundTagUtil.getListTag(chunkData, "Sections", 10);
|
||||||
|
// try lower-case "sections" if capital "Sections" is missing
|
||||||
|
if (tagSections == null
|
||||||
|
|| tagSections.isEmpty())
|
||||||
|
{
|
||||||
|
tagSections = CompoundTagUtil.getListTag(chunkData, "sections", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boolean blocksFound = false;
|
||||||
|
if (tagSections != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < tagSections.size(); ++i)
|
||||||
|
{
|
||||||
|
CompoundTag tagSection = CompoundTagUtil.getCompoundTag(tagSections, i);
|
||||||
|
if (tagSection == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int sectionYPos = CompoundTagUtil.getByte(tagSection, "Y");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// get blocks/biomes //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
if (tagSection.contains("Palette", 9)
|
||||||
|
&& tagSection.contains("BlockStates", 12))
|
||||||
|
{
|
||||||
|
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
||||||
|
levelChunkSection.getStates().read(tagSection.getList("Palette", 10), tagSection.getLongArray("BlockStates"));
|
||||||
|
levelChunkSection.recalcBlockCounts();
|
||||||
|
if (!levelChunkSection.isEmpty())
|
||||||
|
{
|
||||||
|
int sectionIndex;
|
||||||
|
#if MC_VER < MC_1_17_1
|
||||||
|
sectionIndex = sectionYPos;
|
||||||
|
#else
|
||||||
|
sectionIndex = level.getSectionIndexFromSectionY(sectionYPos);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chunkSections[sectionIndex] = levelChunkSection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
||||||
|
if (sectionId >= 0
|
||||||
|
&& sectionId < chunkSections.length)
|
||||||
|
{
|
||||||
|
//========//
|
||||||
|
// blocks //
|
||||||
|
//========//
|
||||||
|
|
||||||
|
PalettedContainer<BlockState> blockStateContainer;
|
||||||
|
|
||||||
|
boolean containsBlockStates = CompoundTagUtil.contains(tagSection, "block_states", 10);
|
||||||
|
if (containsBlockStates)
|
||||||
|
{
|
||||||
|
Codec<PalettedContainer<BlockState>> blockStateCodec = getBlockStateCodec(level);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
blockStateContainer = blockStateCodec
|
||||||
|
.parse(NbtOps.INSTANCE, CompoundTagUtil.getCompoundTag(tagSection, "block_states"))
|
||||||
|
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||||
|
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
||||||
|
#else
|
||||||
|
blockStateContainer = blockStateCodec
|
||||||
|
.parse(NbtOps.INSTANCE, CompoundTagUtil.getCompoundTag(tagSection, "block_states"))
|
||||||
|
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
||||||
|
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
blocksFound = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_9
|
||||||
|
blockStateContainer = new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||||
|
#else
|
||||||
|
blockStateContainer = PalettedContainerFactory.create(level.registryAccess()).createForBlockStates();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// biomes //
|
||||||
|
//========//
|
||||||
|
|
||||||
|
Registry<Biome> biomeRegistry = getBiomeRegistry(level);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
Codec<PalettedContainer<Biome>> biomeCodec;
|
||||||
|
#else
|
||||||
|
Codec<PalettedContainer<Holder<Biome>>> biomeCodec;
|
||||||
|
#endif
|
||||||
|
biomeCodec = getBiomeCodec(level, biomeRegistry);
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
PalettedContainer<Biome> biomeContainer;
|
||||||
|
#else
|
||||||
|
PalettedContainer<Holder<Biome>> biomeContainer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
biomeContainer = tagSection.contains("biomeRegistry", 10)
|
||||||
|
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomeRegistry")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
||||||
|
: new PalettedContainer<Biome>(biomeRegistry, biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
CompoundTag biomeTag = CompoundTagUtil.getCompoundTag(tagSection, "biomeRegistry");
|
||||||
|
if (biomeTag == null)
|
||||||
|
{
|
||||||
|
biomeTag = CompoundTagUtil.getCompoundTag(tagSection, "biomes");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (biomeTag != null
|
||||||
|
&& !biomeTag.isEmpty())
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_20_6
|
||||||
|
biomeContainer = new PalettedContainer<Holder<Biome>>(
|
||||||
|
biomeRegistry.asHolderIdMap(),
|
||||||
|
biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
#else
|
||||||
|
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, biomeTag)
|
||||||
|
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYCount, (String) string))
|
||||||
|
.getOrThrow((message) -> logErrorAndReturnException(message));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no biomes found, use the default (probably plains)
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_3
|
||||||
|
biomeContainer = new PalettedContainer<Holder<Biome>>(
|
||||||
|
biomeRegistry.asHolderIdMap(),
|
||||||
|
biomeRegistry.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
#elif MC_VER < MC_1_21_9
|
||||||
|
biomeContainer = new PalettedContainer<Holder<Biome>>(biomeRegistry.asHolderIdMap(),
|
||||||
|
biomeRegistry.getOrThrow(Biomes.PLAINS),
|
||||||
|
PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
#else
|
||||||
|
biomeContainer = PalettedContainerFactory.create(level.registryAccess()).createForBiomes();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_20_1
|
||||||
|
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||||
|
#else
|
||||||
|
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocksFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Codec<PalettedContainer<BlockState>> getBlockStateCodec(LevelAccessor level)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
return null; // unused for older MC versions
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
return PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||||
|
#elif MC_VER <= MC_1_21_8
|
||||||
|
return PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||||
|
#else
|
||||||
|
return PalettedContainerFactory.create(level.registryAccess()).blockStatesContainerCodec();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Registry<Biome> getBiomeRegistry(LevelAccessor level)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
// not needed
|
||||||
|
return null;
|
||||||
|
#elif MC_VER < MC_1_19_4
|
||||||
|
return level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||||
|
#elif MC_VER < MC_1_21_3
|
||||||
|
return level.registryAccess().registryOrThrow(Registries.BIOME);
|
||||||
|
#else
|
||||||
|
return level.registryAccess().lookupOrThrow(Registries.BIOME);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
private static
|
||||||
|
#if MC_VER < MC_1_19_2 Codec<PalettedContainer<Biome>>
|
||||||
|
#else Codec<PalettedContainer<Holder<Biome>>>
|
||||||
|
#endif
|
||||||
|
getBiomeCodec(LevelAccessor level, Registry<Biome> biomeRegistry)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
return null; // unused for older MC versions
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
return PalettedContainer.codec(
|
||||||
|
biomeRegistry, biomeRegistry.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS));
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
return PalettedContainer.codec(
|
||||||
|
biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getHolderOrThrow(Biomes.PLAINS));
|
||||||
|
#elif MC_VER < MC_1_21_3
|
||||||
|
return PalettedContainer.codecRW(
|
||||||
|
biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getHolderOrThrow(Biomes.PLAINS));
|
||||||
|
#elif MC_VER < MC_1_21_9
|
||||||
|
return PalettedContainer.codecRW(
|
||||||
|
biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS));
|
||||||
|
#else
|
||||||
|
return PalettedContainer.codecRW(
|
||||||
|
biomeRegistry.holderByNameCodec(), PalettedContainerFactory.create(level.registryAccess()).biomeStrategy(), biomeRegistry.getOrThrow(Biomes.PLAINS));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// heightmaps //
|
||||||
|
//============//
|
||||||
|
|
||||||
|
private static boolean readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
CompoundTag tagHeightmaps = CompoundTagUtil.getCompoundTag(chunkData, "Heightmaps");
|
||||||
|
if (tagHeightmaps == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||||
|
{
|
||||||
|
String heightmapKey = type.getSerializationKey();
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
if (tagHeightmaps.contains(heightmapKey, 12))
|
||||||
|
{
|
||||||
|
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmapKey));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (tagHeightmaps.contains(heightmapKey))
|
||||||
|
{
|
||||||
|
Optional<long[]> optionalHeightmap = tagHeightmaps.getLongArray(heightmapKey);
|
||||||
|
if (optionalHeightmap.isPresent())
|
||||||
|
{
|
||||||
|
chunk.setHeightmap(type, optionalHeightmap.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// chunk lighting //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
/** source: https://minecraft.wiki/w/Chunk_format */
|
||||||
|
public static CombinedChunkLightStorage readLight(ChunkAccess chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_17_1
|
||||||
|
// MC 1.16 and 1.17 doesn't have the necessary NBT info
|
||||||
|
return null;
|
||||||
|
#else
|
||||||
|
|
||||||
|
CombinedChunkLightStorage combinedStorage = new CombinedChunkLightStorage(ChunkWrapper.getInclusiveMinBuildHeight(chunk), ChunkWrapper.getExclusiveMaxBuildHeight(chunk));
|
||||||
|
ChunkLightStorage blockLightStorage = combinedStorage.blockLightStorage;
|
||||||
|
ChunkLightStorage skyLightStorage = combinedStorage.skyLightStorage;
|
||||||
|
|
||||||
|
boolean foundSkyLight = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// get NBT tags info //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
Tag chunkSectionTags = chunkData.get("sections");
|
||||||
|
if (chunkSectionTags == null)
|
||||||
|
{
|
||||||
|
if (!lightingSectionErrorLogged)
|
||||||
|
{
|
||||||
|
lightingSectionErrorLogged = true;
|
||||||
|
LOGGER.error("No sections found for chunk at pos ["+chunk.getPos()+"] chunk data may be out of date.");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (!(chunkSectionTags instanceof ListTag))
|
||||||
|
{
|
||||||
|
if (!lightingSectionErrorLogged)
|
||||||
|
{
|
||||||
|
lightingSectionErrorLogged = true;
|
||||||
|
LOGGER.error("Chunk section tag list have unexpected type ["+chunkSectionTags.getClass().getName()+"], expected ["+ListTag.class.getName()+"].");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ListTag chunkSectionListTag = (ListTag) chunkSectionTags;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// get lighting info //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
for (int sectionIndex = 0; sectionIndex < chunkSectionListTag.size(); sectionIndex++)
|
||||||
|
{
|
||||||
|
Tag chunkSectionTag = chunkSectionListTag.get(sectionIndex);
|
||||||
|
if (!(chunkSectionTag instanceof CompoundTag))
|
||||||
|
{
|
||||||
|
if (!lightingSectionErrorLogged)
|
||||||
|
{
|
||||||
|
lightingSectionErrorLogged = true;
|
||||||
|
LOGGER.error("Chunk section tag has an unexpected type ["+chunkSectionTag.getClass().getName()+"], expected ["+CompoundTag.class.getName()+"].");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CompoundTag chunkSectionCompoundTag = (CompoundTag) chunkSectionTag;
|
||||||
|
|
||||||
|
|
||||||
|
// if null all lights = 0
|
||||||
|
byte[] blockLightNibbleArray = CompoundTagUtil.getByteArray(chunkSectionCompoundTag, "BlockLight");
|
||||||
|
byte[] skyLightNibbleArray = CompoundTagUtil.getByteArray(chunkSectionCompoundTag, "SkyLight");
|
||||||
|
|
||||||
|
if (blockLightNibbleArray != null
|
||||||
|
&& skyLightNibbleArray != null)
|
||||||
|
{
|
||||||
|
// if any sky light was found then all lights above will be max brightness
|
||||||
|
if (skyLightNibbleArray.length != 0)
|
||||||
|
{
|
||||||
|
foundSkyLight = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
||||||
|
{
|
||||||
|
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
||||||
|
{
|
||||||
|
// chunk sections are also 16 blocks tall
|
||||||
|
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
||||||
|
{
|
||||||
|
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
||||||
|
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
||||||
|
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
||||||
|
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
||||||
|
{
|
||||||
|
skyLight = LodUtil.MAX_MC_LIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
||||||
|
blockLightStorage.set(relX, y, relZ, blockLight);
|
||||||
|
skyLightStorage.set(relX, y, relZ, skyLight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinedStorage;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/** source: https://minecraft.wiki/w/Chunk_format#Block_Format */
|
||||||
|
private static byte getNibbleAtIndex(byte[] arr, int index)
|
||||||
|
{
|
||||||
|
if (index % 2 == 0)
|
||||||
|
{
|
||||||
|
return (byte)(arr[index/2] & 0x0F);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (byte)((arr[index/2]>>4) & 0x0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// logging //
|
||||||
|
//=========//
|
||||||
|
|
||||||
|
private static void logBlockDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
||||||
|
{
|
||||||
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private static void logBiomeDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
||||||
|
{
|
||||||
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void logParsingWarningOnce(String message) { logParsingWarningOnce(message, null); }
|
||||||
|
private static void logParsingWarningOnce(String message, Exception e)
|
||||||
|
{
|
||||||
|
if (message == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.",
|
||||||
|
e);
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RuntimeException logErrorAndReturnException(String message)
|
||||||
|
{
|
||||||
|
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
||||||
|
{
|
||||||
|
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
||||||
|
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Currently we want to ignore these errors, if returning null is a problem, we can change this later
|
||||||
|
return null; //new RuntimeException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
public static class CombinedChunkLightStorage
|
||||||
|
{
|
||||||
|
public ChunkLightStorage blockLightStorage;
|
||||||
|
public ChunkLightStorage skyLightStorage;
|
||||||
|
|
||||||
|
public CombinedChunkLightStorage(int minY, int maxY)
|
||||||
|
{
|
||||||
|
this.blockLightStorage = ChunkLightStorage.createBlockLightStorage(minY, maxY);
|
||||||
|
this.skyLightStorage = ChunkLightStorage.createSkyLightStorage(minY, maxY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+343
@@ -0,0 +1,343 @@
|
|||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
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.pos.DhChunkPos;
|
||||||
|
import com.seibel.distanthorizons.core.util.ExceptionUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
|
import net.minecraft.world.level.chunk.storage.IOWorker;
|
||||||
|
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.channels.ClosedByInterruptException;
|
||||||
|
import java.nio.channels.ClosedChannelException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_17_1
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#elif MC_VER <= MC_1_19_2
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
#elif MC_VER <= MC_1_19_4
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
#elif MC_VER <= MC_1_20_6
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
#elif MC_VER <= MC_1_21_3
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#elif MC_VER <= MC_1_21_8
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
|
#elif MC_VER <= MC_1_21_9
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainerFactory;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainerFactory;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public class ChunkFileReader implements AutoCloseable
|
||||||
|
{
|
||||||
|
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.name("LOD World Gen")
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logWorldGenEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final DhLogger CHUNK_LOAD_LOGGER = new DhLoggerBuilder()
|
||||||
|
.name("LOD Chunk Loading")
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logWorldGenChunkLoadEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static final IModChecker MOD_CHECKER = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||||
|
|
||||||
|
public final GlobalWorldGenParams params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* will be true if C2ME is installed (since they require us to
|
||||||
|
* pull chunks using their async method), or if there
|
||||||
|
* was an issue with the sync pulling method.
|
||||||
|
*/
|
||||||
|
private boolean pullExistingChunkUsingMcAsyncMethod = false;
|
||||||
|
|
||||||
|
private final AtomicReference<RegionFileStorageExternalCache> regionFileStorageCacheRef = new AtomicReference<>();
|
||||||
|
public RegionFileStorageExternalCache getOrCreateRegionFileCache(RegionFileStorage storage)
|
||||||
|
{
|
||||||
|
RegionFileStorageExternalCache cache = this.regionFileStorageCacheRef.get();
|
||||||
|
if (cache == null)
|
||||||
|
{
|
||||||
|
cache = new RegionFileStorageExternalCache(storage);
|
||||||
|
if (!this.regionFileStorageCacheRef.compareAndSet(null, cache))
|
||||||
|
{
|
||||||
|
cache = this.regionFileStorageCacheRef.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public ChunkFileReader(GlobalWorldGenParams params)
|
||||||
|
{
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
|
if (MOD_CHECKER.isModLoaded("c2me"))
|
||||||
|
{
|
||||||
|
LOGGER.info("C2ME detected: DH's pre-existing chunk accessing will use methods handled by C2ME.");
|
||||||
|
this.pullExistingChunkUsingMcAsyncMethod = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the given chunk pos already exists in the world, that chunk will be returned,
|
||||||
|
* otherwise this will return an empty chunk.
|
||||||
|
*/
|
||||||
|
public CompletableFuture<ChunkWrapper> createEmptyOrPreExistingChunkWrapperAsync(
|
||||||
|
int chunkX, int chunkZ,
|
||||||
|
Map<DhChunkPos, ChunkLightStorage> chunkSkyLightingByDhPos,
|
||||||
|
Map<DhChunkPos, ChunkLightStorage> chunkBlockLightingByDhPos,
|
||||||
|
Map<DhChunkPos, ChunkWrapper> generatedChunkWrapperByDhPos)
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||||
|
DhChunkPos dhChunkPos = new DhChunkPos(chunkX, chunkZ);
|
||||||
|
|
||||||
|
if (generatedChunkWrapperByDhPos.containsKey(dhChunkPos))
|
||||||
|
{
|
||||||
|
return CompletableFuture.completedFuture(generatedChunkWrapperByDhPos.get(dhChunkPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getChunkNbtDataAsync(chunkPos)
|
||||||
|
.thenApply((CompoundTag chunkData) ->
|
||||||
|
{
|
||||||
|
ChunkWrapper newChunkWrapper = this.loadOrMakeChunkWrapper(chunkPos, chunkData);
|
||||||
|
|
||||||
|
// attempt to get chunk lighting
|
||||||
|
ChunkCompoundTagParser.CombinedChunkLightStorage combinedLights = ChunkCompoundTagParser.readLight(newChunkWrapper.getChunk(), chunkData);
|
||||||
|
if (combinedLights != null)
|
||||||
|
{
|
||||||
|
// may be empty, empty checks are handled later
|
||||||
|
chunkSkyLightingByDhPos.put(dhChunkPos, combinedLights.skyLightStorage);
|
||||||
|
chunkBlockLightingByDhPos.put(dhChunkPos, combinedLights.blockLightStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newChunkWrapper;
|
||||||
|
})
|
||||||
|
// separate handle so we can cleanly handle missing chunks and/or thrown errors
|
||||||
|
.handle((ChunkWrapper newChunkWrapper, Throwable throwable) ->
|
||||||
|
{
|
||||||
|
if (newChunkWrapper != null)
|
||||||
|
{
|
||||||
|
return newChunkWrapper;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this.CreateProtoChunkWrapper(this.params.mcServerLevel, chunkPos);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.thenApply((ChunkWrapper newChunkWrapper) ->
|
||||||
|
{
|
||||||
|
generatedChunkWrapperByDhPos.put(dhChunkPos, newChunkWrapper);
|
||||||
|
return newChunkWrapper;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private CompletableFuture<CompoundTag> getChunkNbtDataAsync(ChunkPos chunkPos)
|
||||||
|
{
|
||||||
|
ServerLevel level = this.params.mcServerLevel;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IOWorker ioWorker = level.getChunkSource().chunkMap.worker;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_18_2
|
||||||
|
return CompletableFuture.completedFuture(ioWorker.load(chunkPos));
|
||||||
|
#else
|
||||||
|
|
||||||
|
// storage will be null if C2ME is installed
|
||||||
|
if (!this.pullExistingChunkUsingMcAsyncMethod
|
||||||
|
&& ioWorker.storage != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RegionFileStorage storage = this.params.mcServerLevel.getChunkSource().chunkMap.worker.storage;
|
||||||
|
RegionFileStorageExternalCache cache = this.getOrCreateRegionFileCache(storage);
|
||||||
|
return CompletableFuture.completedFuture(cache.read(chunkPos));
|
||||||
|
}
|
||||||
|
catch (NullPointerException e)
|
||||||
|
{
|
||||||
|
// this shouldn't happen, if anything is null it should be
|
||||||
|
// ioWorker.storage
|
||||||
|
// but just in case
|
||||||
|
LOGGER.error("Unexpected issue pulling pre-existing chunk ["+chunkPos+"], falling back to async chunk pulling. This may cause server-tick lag.", e);
|
||||||
|
this.pullExistingChunkUsingMcAsyncMethod = true;
|
||||||
|
|
||||||
|
// try again now using the async method
|
||||||
|
return this.getChunkNbtDataAsync(chunkPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// log if we unexpectedly weren't able to run the sync chunk pulling
|
||||||
|
if (!this.pullExistingChunkUsingMcAsyncMethod)
|
||||||
|
{
|
||||||
|
// this shouldn't happen, but just in case
|
||||||
|
LOGGER.info("Unable to pull pre-existing chunk using synchronous method. Falling back to async method. this may cause server-tick lag.");
|
||||||
|
this.pullExistingChunkUsingMcAsyncMethod = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//GET_CHUNK_COUNT_REF.incrementAndGet();
|
||||||
|
|
||||||
|
// When running in vanilla MC on versions before 1.21.4,
|
||||||
|
// DH would attempt to run loadAsync on this same thread via a threading mixin,
|
||||||
|
// to prevent causing lag on the server thread.
|
||||||
|
// However, if a mod like C2ME is installed this will run on a C2ME thread instead.
|
||||||
|
return ioWorker.loadAsync(chunkPos)
|
||||||
|
.thenApply(optional ->
|
||||||
|
{
|
||||||
|
// Debugging note:
|
||||||
|
// If there are reports of extreme memory use when C2ME is installed, that probably means
|
||||||
|
// this method is queuing a lot of tasks (1,000+), which causes C2ME to explode.
|
||||||
|
|
||||||
|
//GET_CHUNK_COUNT_REF.decrementAndGet();
|
||||||
|
//PREF_LOGGER.info("chunk getter count ["+F3Screen.NUMBER_FORMAT.format(GET_CHUNK_COUNT_REF.get())+"]");
|
||||||
|
return optional.orElse(null);
|
||||||
|
})
|
||||||
|
.exceptionally((throwable) ->
|
||||||
|
{
|
||||||
|
// unwrap the CompletionException if necessary
|
||||||
|
Throwable actualThrowable = throwable;
|
||||||
|
while (actualThrowable instanceof CompletionException completionException)
|
||||||
|
{
|
||||||
|
actualThrowable = completionException.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isShutdownException = ExceptionUtil.isShutdownException(actualThrowable);
|
||||||
|
if (!isShutdownException)
|
||||||
|
{
|
||||||
|
CHUNK_LOAD_LOGGER.warn("DistantHorizons: Couldn't load or make chunk ["+chunkPos+"], error: ["+actualThrowable.getMessage()+"].", actualThrowable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (ClosedByInterruptException ignore)
|
||||||
|
{
|
||||||
|
// this just means the world generator is being shut down
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
CHUNK_LOAD_LOGGER.warn("Couldn't load or make chunk [" + chunkPos + "]. Error: [" + e.getMessage() + "].", e);
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private ChunkWrapper loadOrMakeChunkWrapper(ChunkPos chunkPos, CompoundTag chunkTagData)
|
||||||
|
{
|
||||||
|
ServerLevel mcServerLevel = this.params.mcServerLevel;
|
||||||
|
|
||||||
|
if (chunkTagData == null)
|
||||||
|
{
|
||||||
|
return this.CreateProtoChunkWrapper(mcServerLevel, chunkPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ChunkWrapper chunkWrapper = ChunkCompoundTagParser.createFromTag(mcServerLevel, this.params.dhServerLevel, chunkPos, chunkTagData);
|
||||||
|
if (chunkWrapper == null)
|
||||||
|
{
|
||||||
|
chunkWrapper = this.CreateProtoChunkWrapper(mcServerLevel, chunkPos);
|
||||||
|
}
|
||||||
|
return chunkWrapper;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
CHUNK_LOAD_LOGGER.error(
|
||||||
|
"DistantHorizons: couldn't load or make chunk at [" + chunkPos + "]." +
|
||||||
|
"Please try optimizing your world to fix this issue. \n" +
|
||||||
|
"World optimization can be done from the singleplayer world selection screen.\n" +
|
||||||
|
"Error: [" + e.getMessage() + "]."
|
||||||
|
, e);
|
||||||
|
|
||||||
|
return this.CreateProtoChunkWrapper(mcServerLevel, chunkPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkWrapper CreateProtoChunkWrapper(ServerLevel level, ChunkPos chunkPos)
|
||||||
|
{
|
||||||
|
ProtoChunk chunk = CreateProtoChunk(level, chunkPos);
|
||||||
|
return new ChunkWrapper(chunk, this.params.dhServerLevel.getLevelWrapper());
|
||||||
|
}
|
||||||
|
public static ProtoChunk CreateProtoChunk(ServerLevel level, ChunkPos chunkPos)
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_16_5
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY);
|
||||||
|
#elif MC_VER <= MC_1_17_1
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level);
|
||||||
|
#elif MC_VER <= MC_1_19_2
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
|
||||||
|
#elif MC_VER <= MC_1_19_4
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registries.BIOME), null);
|
||||||
|
#elif MC_VER < MC_1_21_3
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registries.BIOME), null);
|
||||||
|
#elif MC_VER < MC_1_21_9
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().lookupOrThrow(Registries.BIOME), null);
|
||||||
|
#else
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, PalettedContainerFactory.create(level.registryAccess()), null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
RegionFileStorageExternalCache regionStorage = this.regionFileStorageCacheRef.get();
|
||||||
|
if (regionStorage != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
regionStorage.close();
|
||||||
|
}
|
||||||
|
catch (ClosedChannelException ignore) { /* world generator is being shut down */ }
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
LOGGER.error("Failed to close region file storage cache, error: ["+e.getMessage()+"].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+148
@@ -0,0 +1,148 @@
|
|||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* these tag helpers are usedd to simplify tag accessing between MC versions
|
||||||
|
*/
|
||||||
|
public class CompoundTagUtil
|
||||||
|
{
|
||||||
|
|
||||||
|
/** defaults to "false" if the tag isn't present */
|
||||||
|
public static boolean getBoolean(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getBoolean(key);
|
||||||
|
#else
|
||||||
|
return tag.getBoolean(key).orElse(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
public static byte getByte(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getByte(key);
|
||||||
|
#else
|
||||||
|
return tag.getByte(key).orElse((byte)0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
public static short getShort(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getShort(index);
|
||||||
|
#else
|
||||||
|
return tag.getShort(index).orElse((short)0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
public static int getInt(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getInt(key);
|
||||||
|
#else
|
||||||
|
return tag.getInt(key).orElse(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to "0" if the tag isn't present */
|
||||||
|
public static long getLong(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getInt(key);
|
||||||
|
#else
|
||||||
|
return tag.getLong(key).orElse(0L);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
public static String getString(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getString(key);
|
||||||
|
#else
|
||||||
|
return tag.getString(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
public static byte[] getByteArray(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getByteArray(key);
|
||||||
|
#else
|
||||||
|
return tag.getByteArray(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
public static CompoundTag getCompoundTag(CompoundTag tag, String key)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getCompound(key);
|
||||||
|
#else
|
||||||
|
return tag.getCompound(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
public static CompoundTag getCompoundTag(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getCompound(index);
|
||||||
|
#else
|
||||||
|
return tag.getCompound(index).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* defaults to null if the tag isn't present
|
||||||
|
* @param elementType unused after MC 1.21.5
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static ListTag getListTag(CompoundTag tag, String key, int elementType)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getList(key, elementType);
|
||||||
|
#else
|
||||||
|
return tag.getList(key).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** defaults to null if the tag isn't present */
|
||||||
|
@Nullable
|
||||||
|
public static ListTag getListTag(ListTag tag, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.getList(index);
|
||||||
|
#else
|
||||||
|
return tag.getList(index).orElse(null);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean contains(CompoundTag tag, String key, int index)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_21_5
|
||||||
|
return tag.contains(key, index);
|
||||||
|
#else
|
||||||
|
return tag.contains(key);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
-875
@@ -1,875 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU GPL 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 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
|
||||||
import com.mojang.serialization.Dynamic;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.shorts.ShortList;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
#if MC_VER >= MC_1_19_4
|
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
|
||||||
#endif
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.nbt.ListTag;
|
|
||||||
import net.minecraft.nbt.NbtOps;
|
|
||||||
import net.minecraft.nbt.Tag;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.level.*;
|
|
||||||
import net.minecraft.world.level.biome.Biome;
|
|
||||||
import net.minecraft.world.level.biome.Biomes;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.Blocks;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.world.level.chunk.*;
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
|
||||||
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
|
||||||
#endif
|
|
||||||
import net.minecraft.world.ticks.LevelChunkTicks;
|
|
||||||
#endif
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
import net.minecraft.core.Holder;
|
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
|
||||||
import net.minecraft.world.level.material.Fluids;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MC_VER == MC_1_20_6
|
|
||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.status.ChunkType;
|
|
||||||
#elif MC_VER >= MC_1_21_1
|
|
||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|
||||||
import net.minecraft.world.level.chunk.status.ChunkType;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
import net.minecraft.world.level.material.Fluid;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
|
|
||||||
public class ChunkFileReader
|
|
||||||
{
|
|
||||||
private static final AtomicBoolean ZERO_CHUNK_POS_ERROR_LOGGED_REF = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_21_10
|
|
||||||
// BLOCK_STATE_CODEC can no longer be statically created since
|
|
||||||
// it needs a level reference
|
|
||||||
#elif MC_VER >= MC_1_19_2
|
|
||||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
|
||||||
#elif MC_VER >= MC_1_18_2
|
|
||||||
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private static final String TAG_UPGRADE_DATA = "UpgradeData";
|
|
||||||
private static final String BLOCK_TICKS_TAG_18 = "block_ticks";
|
|
||||||
private static final String FLUID_TICKS_TAG_18 = "fluid_ticks";
|
|
||||||
private static final String BLOCK_TICKS_TAG_PRE18 = "TileTicks";
|
|
||||||
private static final String FLUID_TICKS_TAG_PRE18 = "LiquidTicks";
|
|
||||||
private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER;
|
|
||||||
|
|
||||||
private static boolean lightingSectionErrorLogged = false;
|
|
||||||
|
|
||||||
private static final ConcurrentHashMap<String, Object> LOGGED_ERROR_MESSAGE_MAP = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============//
|
|
||||||
// read chunk //
|
|
||||||
//============//
|
|
||||||
|
|
||||||
public static LevelChunk read(WorldGenLevel level, ChunkPos chunkPos, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
CompoundTag tagLevel = chunkData.getCompound("Level");
|
|
||||||
#else
|
|
||||||
CompoundTag tagLevel = chunkData;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int chunkX = tagGetInt(tagLevel,"xPos");
|
|
||||||
int chunkZ = tagGetInt(tagLevel, "zPos");
|
|
||||||
ChunkPos actualPos = new ChunkPos(chunkX, chunkZ);
|
|
||||||
|
|
||||||
if (!Objects.equals(chunkPos, actualPos))
|
|
||||||
{
|
|
||||||
if (chunkX == 0 && chunkZ == 0)
|
|
||||||
{
|
|
||||||
if (!ZERO_CHUNK_POS_ERROR_LOGGED_REF.getAndSet(true))
|
|
||||||
{
|
|
||||||
// explicit chunkPos toString is necessary otherwise the JDK 17 compiler breaks
|
|
||||||
LOGGER.warn("Chunk file at ["+chunkPos.toString()+"] doesn't have a chunk pos. \n" +
|
|
||||||
"This might happen if the world was created using an external program. \n" +
|
|
||||||
"DH will attempt to parse the chunk anyway and won't log this message again.\n" +
|
|
||||||
"If issues arise please try optimizing your world to fix this issue. \n" +
|
|
||||||
"World optimization can be done from the singleplayer world selection screen."+
|
|
||||||
"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// everything is on one line to fix a JDK 17 compiler issue
|
|
||||||
// if the issue is ever resolved, feel free to make this multi-line for readability
|
|
||||||
LOGGER.error("Chunk file at ["+chunkPos.toString()+"] is in the wrong location. \nPlease try optimizing your world to fix this issue. \nWorld optimization can be done from the singleplayer world selection screen. \n(Expected pos: ["+chunkPos.toString()+"], actual ["+actualPos.toString()+"])");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_6
|
|
||||||
ChunkStatus.ChunkType chunkType;
|
|
||||||
#else
|
|
||||||
ChunkType chunkType;
|
|
||||||
#endif
|
|
||||||
chunkType = readChunkType(tagLevel);
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
|
|
||||||
return null;
|
|
||||||
#elif MC_VER < MC_1_21_6
|
|
||||||
|
|
||||||
BlendingData blendingData = readBlendingData(tagLevel);
|
|
||||||
#if MC_VER < MC_1_19_2
|
|
||||||
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
|
|
||||||
return null;
|
|
||||||
#else
|
|
||||||
if (chunkType == #if MC_VER < MC_1_20_6 ChunkStatus.ChunkType.PROTOCHUNK #else ChunkType.PROTOCHUNK #endif && blendingData == null)
|
|
||||||
return null;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
|
|
||||||
// ignore blending data, there appears to be an issue with parsing it in 1.21.6
|
|
||||||
BlendingData blendingData = null;
|
|
||||||
|
|
||||||
if (chunkType == ChunkType.PROTOCHUNK)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
long inhabitedTime = tagGetLong(tagLevel, "InhabitedTime");
|
|
||||||
|
|
||||||
//================== Read params for making the LevelChunk ==================
|
|
||||||
|
|
||||||
UpgradeData upgradeData = UpgradeData.EMPTY;
|
|
||||||
// commented out 2025-06-04 as a test to see if the upgrade data
|
|
||||||
// is actually necessary for DH or if it can be ignored
|
|
||||||
// (if it can't be ignored we'll need to handle null responses from tagGetCompoundTag())
|
|
||||||
//
|
|
||||||
//#if MC_VER < MC_1_17_1
|
|
||||||
//upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
|
||||||
// ? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA))
|
|
||||||
// : UpgradeData.EMPTY;
|
|
||||||
//#elif MC_VER < MC_1_21_5
|
|
||||||
//upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
|
|
||||||
// ? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA), level)
|
|
||||||
// : UpgradeData.EMPTY;
|
|
||||||
//#else
|
|
||||||
//upgradeData = tagLevel.contains(TAG_UPGRADE_DATA)
|
|
||||||
// ? new UpgradeData(tagGetCompoundTag(tagLevel, TAG_UPGRADE_DATA), level)
|
|
||||||
// : UpgradeData.EMPTY;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
|
|
||||||
boolean isLightOn = tagGetBoolean(tagLevel, "isLightOn");
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
|
|
||||||
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if MC_VER >= MC_1_17_1 , level #endif ,
|
|
||||||
chunkPos, level.getLevel().getChunkSource().getGenerator().getBiomeSource(),
|
|
||||||
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
|
|
||||||
|
|
||||||
TickList<Block> blockTicks = tagLevel.contains(BLOCK_TICKS_TAG_PRE18, 9)
|
|
||||||
? ChunkTickList.create(tagLevel.getList(BLOCK_TICKS_TAG_PRE18, 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
|
|
||||||
: new ProtoTickList<Block>(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
|
|
||||||
tagLevel.getList("ToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
|
||||||
|
|
||||||
TickList<Fluid> fluidTicks = tagLevel.contains(FLUID_TICKS_TAG_PRE18, 9)
|
|
||||||
? ChunkTickList.create(tagLevel.getList(FLUID_TICKS_TAG_PRE18, 10), Registry.FLUID::getKey, Registry.FLUID::get)
|
|
||||||
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
|
|
||||||
tagLevel.getList("LiquidsToBeTicked", 9)#if MC_VER >= MC_1_17_1 , level #endif );
|
|
||||||
#else
|
|
||||||
#if MC_VER < MC_1_19_4
|
|
||||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
|
||||||
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
|
||||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
|
||||||
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
|
||||||
#elif MC_VER < MC_1_21_4
|
|
||||||
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
|
|
||||||
(string -> BuiltInRegistries.BLOCK.getOptional(ResourceLocation.tryParse(string))), chunkPos);
|
|
||||||
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(tagLevel.getList(FLUID_TICKS_TAG_18, 10),
|
|
||||||
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
|
||||||
#else
|
|
||||||
// do we need the ticks for what we're doing?
|
|
||||||
LevelChunkTicks<Block> blockTicks = new LevelChunkTicks<>();
|
|
||||||
LevelChunkTicks<Fluid> fluidTicks = new LevelChunkTicks<>();
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LevelChunkSection[] levelChunkSections = readSections(level, chunkPos, tagLevel);
|
|
||||||
|
|
||||||
// ====================== Make the chunk =========================
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
|
|
||||||
fluidTicks, inhabitedTime, levelChunkSections, null);
|
|
||||||
#else
|
|
||||||
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
|
|
||||||
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
|
|
||||||
#endif
|
|
||||||
// Set some states after object creation
|
|
||||||
chunk.setLightCorrect(isLightOn);
|
|
||||||
readHeightmaps(chunk, chunkData);
|
|
||||||
//readPostPocessings(chunk, chunkData);
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
private static LevelChunkSection[] readSections(LevelAccessor level, ChunkPos chunkPos, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_10
|
|
||||||
// BLOCK_STATE_CODEC is created statically
|
|
||||||
// TODO clean up this code separation
|
|
||||||
#else
|
|
||||||
final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainerFactory.create(level.registryAccess()).blockStatesContainerCodec();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
#if MC_VER < MC_1_19_4
|
|
||||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
|
||||||
#elif MC_VER < MC_1_21_3
|
|
||||||
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registries.BIOME);
|
|
||||||
#else
|
|
||||||
Registry<Biome> biomes = level.registryAccess().lookupOrThrow(Registries.BIOME);
|
|
||||||
#endif
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
|
|
||||||
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
|
||||||
#elif MC_VER < MC_1_19_2
|
|
||||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
|
|
||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
|
||||||
#elif MC_VER < MC_1_21_3
|
|
||||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
|
||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
|
||||||
#elif MC_VER < MC_1_21_10
|
|
||||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
|
||||||
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
|
||||||
#else
|
|
||||||
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
|
|
||||||
biomes.holderByNameCodec(), PalettedContainerFactory.create(level.registryAccess()).biomeStrategy(), biomes.getOrThrow(Biomes.PLAINS));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
|
|
||||||
LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex];
|
|
||||||
|
|
||||||
ListTag tagSections = tagGetListTag(chunkData, "Sections", 10);
|
|
||||||
if (tagSections == null || tagSections.isEmpty())
|
|
||||||
{
|
|
||||||
tagSections = tagGetListTag(chunkData, "sections", 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (tagSections != null)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < tagSections.size(); ++j)
|
|
||||||
{
|
|
||||||
CompoundTag tagSection = tagGetCompoundTag(tagSections, j);
|
|
||||||
if (tagSection == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int sectionYPos = tagGetByte(tagSection, "Y");
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
|
|
||||||
{
|
|
||||||
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
|
|
||||||
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
|
|
||||||
tagSection.getLongArray("BlockStates"));
|
|
||||||
levelChunkSection.recalcBlockCounts();
|
|
||||||
if (!levelChunkSection.isEmpty())
|
|
||||||
chunkSections[#if MC_VER < MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
|
|
||||||
= levelChunkSection;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
|
||||||
if (sectionId >= 0 && sectionId < chunkSections.length)
|
|
||||||
{
|
|
||||||
PalettedContainer<BlockState> blockStateContainer;
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
PalettedContainer<Biome> biomeContainer;
|
|
||||||
#else
|
|
||||||
PalettedContainer<Holder<Biome>> biomeContainer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
boolean containsBlockStates;
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
containsBlockStates = tagSection.contains("block_states", 10);
|
|
||||||
#else
|
|
||||||
containsBlockStates = tagSection.contains("block_states");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (containsBlockStates)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_20_6
|
|
||||||
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
|
||||||
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
|
||||||
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
|
||||||
#else
|
|
||||||
blockStateContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "block_states"))
|
|
||||||
.promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string))
|
|
||||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_10
|
|
||||||
blockStateContainer = new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
|
||||||
#else
|
|
||||||
blockStateContainer = PalettedContainerFactory.create(level.registryAccess()).createForBlockStates();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
|
||||||
biomeContainer = tagSection.contains("biomes", 10)
|
|
||||||
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, (message) -> logWarningOnce(message))
|
|
||||||
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
|
||||||
#else
|
|
||||||
|
|
||||||
|
|
||||||
boolean containsBiomes;
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
containsBiomes = tagSection.contains("biomes", 10);
|
|
||||||
#else
|
|
||||||
containsBiomes = tagSection.contains("biomes");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (containsBiomes)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_20_6
|
|
||||||
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
|
||||||
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
|
||||||
.getOrThrow(false, (message) -> logParsingWarningOnce(message));
|
|
||||||
#else
|
|
||||||
biomeContainer = biomeCodec.parse(NbtOps.INSTANCE, tagGetCompoundTag(tagSection, "biomes"))
|
|
||||||
.promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
|
|
||||||
.getOrThrow((message) -> logErrorAndReturnException(message));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_3
|
|
||||||
biomeContainer = new PalettedContainer<Holder<Biome>>(
|
|
||||||
biomes.asHolderIdMap(),
|
|
||||||
biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
|
||||||
#elif MC_VER < MC_1_21_10
|
|
||||||
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
|
|
||||||
biomes.getOrThrow(Biomes.PLAINS),
|
|
||||||
PalettedContainer.Strategy.SECTION_BIOMES);
|
|
||||||
#else
|
|
||||||
biomeContainer = PalettedContainerFactory.create(level.registryAccess()).createForBiomes();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_1
|
|
||||||
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
|
||||||
#else
|
|
||||||
chunkSections[sectionId] = new LevelChunkSection(blockStateContainer, biomeContainer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chunkSections;
|
|
||||||
}
|
|
||||||
private static
|
|
||||||
#if MC_VER < MC_1_20_6 ChunkStatus.ChunkType
|
|
||||||
#elif MC_VER < MC_1_21_1 ChunkType
|
|
||||||
#else ChunkType #endif
|
|
||||||
readChunkType(CompoundTag tagLevel)
|
|
||||||
{
|
|
||||||
String statusString = tagGetString(tagLevel,"Status");
|
|
||||||
if (statusString != null)
|
|
||||||
{
|
|
||||||
ChunkStatus chunkStatus = ChunkStatus.byName(statusString);
|
|
||||||
if (chunkStatus != null)
|
|
||||||
{
|
|
||||||
return chunkStatus.getChunkType();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
|
||||||
return ChunkStatus.ChunkType.PROTOCHUNK;
|
|
||||||
#else
|
|
||||||
return ChunkType.PROTOCHUNK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
CompoundTag tagHeightmaps = tagGetCompoundTag(chunkData, "Heightmaps");
|
|
||||||
if (tagHeightmaps != null)
|
|
||||||
{
|
|
||||||
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
|
||||||
{
|
|
||||||
String heightmap = type.getSerializationKey();
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
if (tagHeightmaps.contains(heightmap, 12))
|
|
||||||
{
|
|
||||||
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (tagHeightmaps.contains(heightmap))
|
|
||||||
{
|
|
||||||
Optional<long[]> optionalHeightmap = tagHeightmaps.getLongArray(heightmap);
|
|
||||||
if (optionalHeightmap.isPresent())
|
|
||||||
{
|
|
||||||
chunk.setHeightmap(type, optionalHeightmap.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// commented out as a test as of 2025-06-04 to see if this is actually necessary for DH
|
|
||||||
// DH probably doesn't need any chunk post-processing data
|
|
||||||
//private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
|
||||||
//{
|
|
||||||
// ListTag tagPostProcessings = tagGetListTag(chunkData,"PostProcessing", 9);
|
|
||||||
// if (tagPostProcessings != null)
|
|
||||||
// {
|
|
||||||
// for (int i = 0; i < tagPostProcessings.size(); ++i)
|
|
||||||
// {
|
|
||||||
// ListTag listTag3 = tagGetListTag(tagPostProcessings, i);
|
|
||||||
// for (int j = 0; j < listTag3.size(); ++j)
|
|
||||||
// {
|
|
||||||
// #if MC_VER < MC_1_21_3
|
|
||||||
// chunk.addPackedPostProcess(listTag3.getShort(j), i);
|
|
||||||
// #else
|
|
||||||
// chunk.addPackedPostProcess(ShortList.of(tagGetShort(listTag3, j)), i);
|
|
||||||
// #endif
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
private static BlendingData readBlendingData(CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
BlendingData blendingData = null;
|
|
||||||
|
|
||||||
|
|
||||||
boolean containsBlendingData;
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
containsBlendingData = chunkData.contains("blending_data", 10);
|
|
||||||
#else
|
|
||||||
containsBlendingData = chunkData.contains("blending_data");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (containsBlendingData)
|
|
||||||
{
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_3
|
|
||||||
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null);
|
|
||||||
#else
|
|
||||||
// blending data appears to have changed as of 1.21.6 causing a class cast exception here due to it being wrapped in a Java.Optional
|
|
||||||
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial((message) -> logParsingWarningOnce(message)).orElse(null));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
String message = e.getMessage();
|
|
||||||
if (message == null || message.trim().isEmpty())
|
|
||||||
{
|
|
||||||
message = "Failed to parse blending data";
|
|
||||||
}
|
|
||||||
|
|
||||||
logParsingWarningOnce(message, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return blendingData;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=====================//
|
|
||||||
// read chunk lighting //
|
|
||||||
//=====================//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* https://minecraft.wiki/w/Chunk_format
|
|
||||||
*/
|
|
||||||
public static CombinedChunkLightStorage readLight(ChunkAccess chunk, CompoundTag chunkData)
|
|
||||||
{
|
|
||||||
#if MC_VER <= MC_1_17_1
|
|
||||||
// MC 1.16 and 1.17 doesn't have the necessary NBT info
|
|
||||||
return null;
|
|
||||||
#else
|
|
||||||
|
|
||||||
CombinedChunkLightStorage combinedStorage = new CombinedChunkLightStorage(ChunkWrapper.getInclusiveMinBuildHeight(chunk), ChunkWrapper.getExclusiveMaxBuildHeight(chunk));
|
|
||||||
ChunkLightStorage blockLightStorage = combinedStorage.blockLightStorage;
|
|
||||||
ChunkLightStorage skyLightStorage = combinedStorage.skyLightStorage;
|
|
||||||
|
|
||||||
boolean foundSkyLight = false;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===================//
|
|
||||||
// get NBT tags info //
|
|
||||||
//===================//
|
|
||||||
|
|
||||||
Tag chunkSectionTags = chunkData.get("sections");
|
|
||||||
if (chunkSectionTags == null)
|
|
||||||
{
|
|
||||||
if (!lightingSectionErrorLogged)
|
|
||||||
{
|
|
||||||
lightingSectionErrorLogged = true;
|
|
||||||
LOGGER.error("No sections found for chunk at pos ["+chunk.getPos()+"] chunk data may be out of date.");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else if (!(chunkSectionTags instanceof ListTag))
|
|
||||||
{
|
|
||||||
if (!lightingSectionErrorLogged)
|
|
||||||
{
|
|
||||||
lightingSectionErrorLogged = true;
|
|
||||||
LOGGER.error("Chunk section tag list have unexpected type ["+chunkSectionTags.getClass().getName()+"], expected ["+ListTag.class.getName()+"].");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ListTag chunkSectionListTag = (ListTag) chunkSectionTags;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===================//
|
|
||||||
// get lighting info //
|
|
||||||
//===================//
|
|
||||||
|
|
||||||
for (int sectionIndex = 0; sectionIndex < chunkSectionListTag.size(); sectionIndex++)
|
|
||||||
{
|
|
||||||
Tag chunkSectionTag = chunkSectionListTag.get(sectionIndex);
|
|
||||||
if (!(chunkSectionTag instanceof CompoundTag))
|
|
||||||
{
|
|
||||||
if (!lightingSectionErrorLogged)
|
|
||||||
{
|
|
||||||
lightingSectionErrorLogged = true;
|
|
||||||
LOGGER.error("Chunk section tag has an unexpected type ["+chunkSectionTag.getClass().getName()+"], expected ["+CompoundTag.class.getName()+"].");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
CompoundTag chunkSectionCompoundTag = (CompoundTag) chunkSectionTag;
|
|
||||||
|
|
||||||
|
|
||||||
// if null all lights = 0
|
|
||||||
byte[] blockLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "BlockLight");
|
|
||||||
byte[] skyLightNibbleArray = tagGetByteArray(chunkSectionCompoundTag, "SkyLight");
|
|
||||||
|
|
||||||
if (blockLightNibbleArray != null
|
|
||||||
&& skyLightNibbleArray != null)
|
|
||||||
{
|
|
||||||
// if any sky light was found then all lights above will be max brightness
|
|
||||||
if (skyLightNibbleArray.length != 0)
|
|
||||||
{
|
|
||||||
foundSkyLight = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
|
||||||
{
|
|
||||||
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
|
||||||
{
|
|
||||||
// chunk sections are also 16 blocks tall
|
|
||||||
for (int relY = 0; relY < LodUtil.CHUNK_WIDTH; relY++)
|
|
||||||
{
|
|
||||||
int blockPosIndex = relY*16*16 + relZ*16 + relX;
|
|
||||||
byte blockLight = (blockLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(blockLightNibbleArray, blockPosIndex);
|
|
||||||
byte skyLight = (skyLightNibbleArray.length == 0) ? 0 : getNibbleAtIndex(skyLightNibbleArray, blockPosIndex);
|
|
||||||
if (skyLightNibbleArray.length == 0 && foundSkyLight)
|
|
||||||
{
|
|
||||||
skyLight = LodUtil.MAX_MC_LIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
|
|
||||||
blockLightStorage.set(relX, y, relZ, blockLight);
|
|
||||||
skyLightStorage.set(relX, y, relZ, skyLight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return combinedStorage;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/** source: https://minecraft.wiki/w/Chunk_format#Block_Format */
|
|
||||||
private static byte getNibbleAtIndex(byte[] arr, int index)
|
|
||||||
{
|
|
||||||
if (index % 2 == 0)
|
|
||||||
{
|
|
||||||
return (byte)(arr[index/2] & 0x0F);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (byte)((arr[index/2]>>4) & 0x0F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=========//
|
|
||||||
// logging //
|
|
||||||
//=========//
|
|
||||||
|
|
||||||
private static void logBlockDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
|
||||||
{
|
|
||||||
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
|
||||||
{
|
|
||||||
LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " +
|
|
||||||
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
|
||||||
|
|
||||||
return newMessage;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
private static void logBiomeDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message)
|
|
||||||
{
|
|
||||||
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
|
||||||
{
|
|
||||||
LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+newMessage+"]. " +
|
|
||||||
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
|
||||||
|
|
||||||
return newMessage;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logParsingWarningOnce(String message) { logParsingWarningOnce(message, null); }
|
|
||||||
private static void logParsingWarningOnce(String message, Exception e)
|
|
||||||
{
|
|
||||||
if (message == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
|
||||||
{
|
|
||||||
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
|
||||||
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.",
|
|
||||||
e);
|
|
||||||
|
|
||||||
return newMessage;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RuntimeException logErrorAndReturnException(String message)
|
|
||||||
{
|
|
||||||
LOGGED_ERROR_MESSAGE_MAP.computeIfAbsent(message, (newMessage) ->
|
|
||||||
{
|
|
||||||
LOGGER.warn("Parsing error: ["+newMessage+"]. " +
|
|
||||||
"This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem.");
|
|
||||||
|
|
||||||
return newMessage;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Currently we want to ignore these errors, if returning null is a problem, we can change this later
|
|
||||||
return null; //new RuntimeException(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//====================//
|
|
||||||
// tag helper methods //
|
|
||||||
//====================//
|
|
||||||
|
|
||||||
// TODO move into separate file (this file is getting long)
|
|
||||||
// these tag helpers are to simplify tag accessing between MC versions
|
|
||||||
|
|
||||||
/** defaults to "false" if the tag isn't present */
|
|
||||||
private static boolean tagGetBoolean(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getBoolean(key);
|
|
||||||
#else
|
|
||||||
return tag.getBoolean(key).orElse(false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** defaults to "0" if the tag isn't present */
|
|
||||||
private static byte tagGetByte(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getByte(key);
|
|
||||||
#else
|
|
||||||
return tag.getByte(key).orElse((byte)0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** defaults to "0" if the tag isn't present */
|
|
||||||
private static short tagGetShort(ListTag tag, int index)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getShort(index);
|
|
||||||
#else
|
|
||||||
return tag.getShort(index).orElse((short)0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** defaults to "0" if the tag isn't present */
|
|
||||||
private static int tagGetInt(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getInt(key);
|
|
||||||
#else
|
|
||||||
return tag.getInt(key).orElse(0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** defaults to "0" if the tag isn't present */
|
|
||||||
private static long tagGetLong(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getInt(key);
|
|
||||||
#else
|
|
||||||
return tag.getLong(key).orElse(0L);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** defaults to null if the tag isn't present */
|
|
||||||
@Nullable
|
|
||||||
private static String tagGetString(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getString(key);
|
|
||||||
#else
|
|
||||||
return tag.getString(key).orElse(null);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** defaults to null if the tag isn't present */
|
|
||||||
@Nullable
|
|
||||||
private static byte[] tagGetByteArray(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getByteArray(key);
|
|
||||||
#else
|
|
||||||
return tag.getByteArray(key).orElse(null);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** defaults to null if the tag isn't present */
|
|
||||||
@Nullable
|
|
||||||
private static CompoundTag tagGetCompoundTag(CompoundTag tag, String key)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getCompound(key);
|
|
||||||
#else
|
|
||||||
return tag.getCompound(key).orElse(null);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/** defaults to null if the tag isn't present */
|
|
||||||
@Nullable
|
|
||||||
private static CompoundTag tagGetCompoundTag(ListTag tag, int index)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getCompound(index);
|
|
||||||
#else
|
|
||||||
return tag.getCompound(index).orElse(null);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* defaults to null if the tag isn't present
|
|
||||||
* @param elementType unused after MC 1.21.5
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private static ListTag tagGetListTag(CompoundTag tag, String key, int elementType)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getList(key, elementType);
|
|
||||||
#else
|
|
||||||
return tag.getList(key).orElse(null);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** defaults to null if the tag isn't present */
|
|
||||||
@Nullable
|
|
||||||
private static ListTag tagGetListTag(ListTag tag, int index)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_21_5
|
|
||||||
return tag.getList(index);
|
|
||||||
#else
|
|
||||||
return tag.getList(index).orElse(null);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
|
||||||
// helper classes //
|
|
||||||
//================//
|
|
||||||
|
|
||||||
public static class CombinedChunkLightStorage
|
|
||||||
{
|
|
||||||
public ChunkLightStorage blockLightStorage;
|
|
||||||
public ChunkLightStorage skyLightStorage;
|
|
||||||
|
|
||||||
public CombinedChunkLightStorage(int minY, int maxY)
|
|
||||||
{
|
|
||||||
this.blockLightStorage = ChunkLightStorage.createBlockLightStorage(minY, maxY);
|
|
||||||
this.skyLightStorage = ChunkLightStorage.createSkyLightStorage(minY, maxY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+7
-6
@@ -28,7 +28,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
|||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import net.minecraft.world.level.block.EntityBlock;
|
import net.minecraft.world.level.block.EntityBlock;
|
||||||
import net.minecraft.world.level.block.SpawnerBlock;
|
import net.minecraft.world.level.block.SpawnerBlock;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ import net.minecraft.world.ticks.LevelTickAccess;
|
|||||||
|
|
||||||
public class DhLitWorldGenRegion extends WorldGenRegion
|
public class DhLitWorldGenRegion extends WorldGenRegion
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
private static ChunkStatus debugTriggeredForStatus = null;
|
private static ChunkStatus debugTriggeredForStatus = null;
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
ChunkAccess chunk = this.getChunkAccess(chunkX, chunkZ, chunkStatus, returnNonNull);
|
ChunkAccess chunk = this.getChunkAccess(chunkX, chunkZ, chunkStatus, returnNonNull);
|
||||||
if (chunk instanceof LevelChunk)
|
if (chunk instanceof LevelChunk)
|
||||||
{
|
{
|
||||||
chunk = new ImposterProtoChunk((LevelChunk) chunk #if MC_VER >= MC_1_18_2 , true #endif );
|
chunk = new ImposterProtoChunk((LevelChunk) chunk #if MC_VER >= MC_1_18_2 ,/* allow writes */ false #endif );
|
||||||
}
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
@@ -392,10 +392,11 @@ public class DhLitWorldGenRegion extends WorldGenRegion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus)
|
if (chunkStatus != ChunkStatus.EMPTY
|
||||||
|
&& chunkStatus != debugTriggeredForStatus)
|
||||||
{
|
{
|
||||||
LOGGER.info("WorldGen requiring " + chunkStatus
|
LOGGER.info("WorldGen requiring [" + chunkStatus + "]"
|
||||||
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
|
+ " is outside the expected range. Returning EMPTY chunk.");
|
||||||
debugTriggeredForStatus = chunkStatus;
|
debugTriggeredForStatus = chunkStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -1,13 +1,13 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtIo;
|
import net.minecraft.nbt.NbtIo;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.storage.RegionFile;
|
import net.minecraft.world.level.chunk.storage.RegionFile;
|
||||||
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@@ -29,7 +29,7 @@ import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
|
|||||||
*/
|
*/
|
||||||
public class RegionFileStorageExternalCache implements AutoCloseable
|
public class RegionFileStorageExternalCache implements AutoCloseable
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
/** Can be null due to the C2ME mod */
|
/** Can be null due to the C2ME mod */
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -55,7 +55,7 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
public RegionFileStorageExternalCache(RegionFileStorage storage) { this.storage = storage; }
|
public RegionFileStorageExternalCache(RegionFileStorage storage) { this.storage = storage; }
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public RegionFile getRegionFile(ChunkPos pos) throws IOException
|
public RegionFile getRegionFile(ChunkPos chunkPos) throws IOException
|
||||||
{
|
{
|
||||||
if (this.storage == null)
|
if (this.storage == null)
|
||||||
{
|
{
|
||||||
@@ -70,8 +70,8 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
long posLong = ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ());
|
long chunkPosLong = ChunkPos.asLong(chunkPos.getRegionX(), chunkPos.getRegionZ());
|
||||||
RegionFile rFile = null;
|
RegionFile regionFile = null;
|
||||||
|
|
||||||
// Check vanilla cache
|
// Check vanilla cache
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
@@ -85,7 +85,7 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
this.getRegionFileLock.lock();
|
this.getRegionFileLock.lock();
|
||||||
|
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
rFile = this.storage.getRegionFile(pos);
|
regionFile = this.storage.getRegionFile(chunkPos);
|
||||||
|
|
||||||
// keeping the region cache size low helps prevent concurrency issues
|
// keeping the region cache size low helps prevent concurrency issues
|
||||||
if (this.storage.regionCache.size() > 150) // max 256
|
if (this.storage.regionCache.size() > 150) // max 256
|
||||||
@@ -97,7 +97,7 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
rFile = this.storage.regionCache.getOrDefault(posLong, null);
|
regionFile = this.storage.regionCache.getOrDefault(chunkPosLong, null);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -139,19 +139,19 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
|
|
||||||
if (retryCount >= maxRetryCount)
|
if (retryCount >= maxRetryCount)
|
||||||
{
|
{
|
||||||
BatchGenerationEnvironment.LOAD_LOGGER.warn("Concurrency issue detected when getting region file for chunk at [" + pos + "].");
|
ChunkFileReader.CHUNK_LOAD_LOGGER.warn("Concurrency issue detected when getting region file for chunk at [" + chunkPos + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (rFile != null)
|
if (regionFile != null)
|
||||||
{
|
{
|
||||||
return rFile;
|
return regionFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then check our custom cache
|
// Then check our custom cache
|
||||||
for (RegionFileCache cache : this.regionFileCache)
|
for (RegionFileCache cache : this.regionFileCache)
|
||||||
{
|
{
|
||||||
if (cache.pos == posLong)
|
if (cache.pos == chunkPosLong)
|
||||||
{
|
{
|
||||||
return cache.file;
|
return cache.file;
|
||||||
}
|
}
|
||||||
@@ -170,22 +170,22 @@ public class RegionFileStorageExternalCache implements AutoCloseable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path regionFilePath = storageFolderPath.resolve("r." + pos.getRegionX() + "." + pos.getRegionZ() + ".mca");
|
Path regionFilePath = storageFolderPath.resolve("r." + chunkPos.getRegionX() + "." + chunkPos.getRegionZ() + ".mca");
|
||||||
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
|
||||||
rFile = new RegionFile(regionFilePath.toFile(), storageFolderPath.toFile(), false);
|
regionFile = new RegionFile(regionFilePath.toFile(), storageFolderPath.toFile(), false);
|
||||||
#elif MC_VER <= MC_1_20_4
|
#elif MC_VER <= MC_1_20_4
|
||||||
rFile = new RegionFile(regionFilePath, storageFolderPath, false);
|
regionFile = new RegionFile(regionFilePath, storageFolderPath, false);
|
||||||
#else
|
#else
|
||||||
rFile = new RegionFile(new RegionStorageInfo("level", null, "level type"), regionFilePath, storageFolderPath, false);
|
regionFile = new RegionFile(new RegionStorageInfo("level", null, "level type"), regionFilePath, storageFolderPath, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this.regionFileCache.add(new RegionFileCache(ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ()), rFile));
|
this.regionFileCache.add(new RegionFileCache(ChunkPos.asLong(chunkPos.getRegionX(), chunkPos.getRegionZ()), regionFile));
|
||||||
while (this.regionFileCache.size() > MAX_CACHE_SIZE)
|
while (this.regionFileCache.size() > MAX_CACHE_SIZE)
|
||||||
{
|
{
|
||||||
this.regionFileCache.poll().file.close();
|
this.regionFileCache.poll().file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return rFile;
|
return regionFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+48
-23
@@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.params;
|
||||||
|
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||||
@@ -27,35 +27,50 @@ import net.minecraft.core.Registry;
|
|||||||
import net.minecraft.core.RegistryAccess;
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
import net.minecraft.world.level.biome.BiomeManager;
|
import net.minecraft.world.level.biome.BiomeManager;
|
||||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
|
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||||
#else
|
#else
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
|
||||||
import net.minecraft.world.level.levelgen.RandomState;
|
import net.minecraft.world.level.levelgen.RandomState;
|
||||||
#if MC_VER >= MC_1_19_4
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||||
import net.minecraft.world.level.levelgen.WorldOptions;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.world.level.storage.WorldData;
|
import net.minecraft.world.level.storage.WorldData;
|
||||||
|
|
||||||
public final class GlobalParameters
|
#if MC_VER < MC_1_19_4
|
||||||
|
#elif MC_VER < MC_1_21_3
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
#else
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_19_4
|
||||||
|
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||||
|
#else
|
||||||
|
import net.minecraft.world.level.levelgen.WorldOptions;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles parameters that are relevant for the entire MC world.
|
||||||
|
*
|
||||||
|
* @see ThreadWorldGenParams
|
||||||
|
*/
|
||||||
|
public final class GlobalWorldGenParams
|
||||||
{
|
{
|
||||||
public final ChunkGenerator generator;
|
public final ChunkGenerator generator;
|
||||||
public final IDhServerLevel lodLevel;
|
public final IDhServerLevel dhServerLevel;
|
||||||
public final ServerLevel level;
|
public final ServerLevel mcServerLevel;
|
||||||
public final Registry<Biome> biomes;
|
public final Registry<Biome> biomes;
|
||||||
public final RegistryAccess registry;
|
public final RegistryAccess registry;
|
||||||
public final long worldSeed;
|
public final long worldSeed;
|
||||||
public final DataFixer fixerUpper;
|
public final DataFixer dataFixer;
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
public final StructureManager structures;
|
public final StructureManager structures;
|
||||||
@@ -72,18 +87,24 @@ public final class GlobalParameters
|
|||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
public final BiomeManager biomeManager;
|
public final BiomeManager biomeManager;
|
||||||
public final ChunkScanAccess chunkScanner; // FIXME: Figure out if this is actually needed
|
public final ChunkScanAccess chunkScanner;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public GlobalParameters(IDhServerLevel lodLevel)
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public GlobalWorldGenParams(IDhServerLevel dhServerLevel)
|
||||||
{
|
{
|
||||||
this.lodLevel = lodLevel;
|
this.dhServerLevel = dhServerLevel;
|
||||||
|
|
||||||
this.level = ((ServerLevelWrapper) lodLevel.getServerLevelWrapper()).getWrappedMcObject();
|
this.mcServerLevel = ((ServerLevelWrapper) dhServerLevel.getServerLevelWrapper()).getWrappedMcObject();
|
||||||
MinecraftServer server = this.level.getServer();
|
MinecraftServer server = this.mcServerLevel.getServer();
|
||||||
WorldData worldData = server.getWorldData();
|
WorldData worldData = server.getWorldData();
|
||||||
this.registry = server.registryAccess();
|
this.registry = server.registryAccess();
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_4
|
#if MC_VER < MC_1_19_4
|
||||||
this.worldGenSettings = worldData.worldGenSettings();
|
this.worldGenSettings = worldData.worldGenSettings();
|
||||||
this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
|
this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
|
||||||
@@ -99,15 +120,19 @@ public final class GlobalParameters
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
this.biomeManager = new BiomeManager(this.level, BiomeManager.obfuscateSeed(this.worldSeed));
|
this.biomeManager = new BiomeManager(this.mcServerLevel, BiomeManager.obfuscateSeed(this.worldSeed));
|
||||||
this.chunkScanner = this.level.getChunkSource().chunkScanner();
|
this.chunkScanner = this.mcServerLevel.getChunkSource().chunkScanner();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this.structures = server.getStructureManager();
|
this.structures = server.getStructureManager();
|
||||||
this.generator = this.level.getChunkSource().getGenerator();
|
this.generator = this.mcServerLevel.getChunkSource().getGenerator();
|
||||||
this.fixerUpper = server.getFixerUpper();
|
this.dataFixer = server.getFixerUpper();
|
||||||
|
|
||||||
#if MC_VER >= MC_1_19_2
|
#if MC_VER >= MC_1_19_2
|
||||||
this.randomState = this.level.getChunkSource().randomState();
|
this.randomState = this.mcServerLevel.getChunkSource().randomState();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.params;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.WorldGenLevel;
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public final class ThreadWorldGenParams
|
||||||
|
{
|
||||||
|
private static final ThreadLocal<ThreadWorldGenParams> LOCAL_PARAM_REF = new ThreadLocal<>();
|
||||||
|
|
||||||
|
|
||||||
|
final ServerLevel level;
|
||||||
|
public WorldGenStructFeatManager structFeatManager = null;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
public StructureCheck structCheck;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
boolean isValid = true;
|
||||||
|
|
||||||
|
// used for some older MC versions
|
||||||
|
private static GlobalWorldGenParams previousGlobalWorldGenParams = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public static ThreadWorldGenParams getOrMake(GlobalWorldGenParams globalParams)
|
||||||
|
{
|
||||||
|
ThreadWorldGenParams threadParam = LOCAL_PARAM_REF.get();
|
||||||
|
if (threadParam != null
|
||||||
|
&& threadParam.isValid
|
||||||
|
&& threadParam.level == globalParams.mcServerLevel)
|
||||||
|
{
|
||||||
|
return threadParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
threadParam = new ThreadWorldGenParams(globalParams);
|
||||||
|
LOCAL_PARAM_REF.set(threadParam);
|
||||||
|
return threadParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThreadWorldGenParams(GlobalWorldGenParams param)
|
||||||
|
{
|
||||||
|
previousGlobalWorldGenParams = param;
|
||||||
|
|
||||||
|
this.level = param.mcServerLevel;
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
this.structFeatManager = new WorldGenStructFeatManager(param.worldGenSettings, this.level);
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
this.structCheck = this.createStructureCheck(param);
|
||||||
|
#else
|
||||||
|
this.structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
||||||
|
param.mcServerLevel.dimension(), param.generator, param.randomState, this.level, param.generator.getBiomeSource(), param.worldSeed,
|
||||||
|
param.dataFixer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// builders //
|
||||||
|
//==========//
|
||||||
|
|
||||||
|
public void makeStructFeatManager(WorldGenLevel genLevel, GlobalWorldGenParams param)
|
||||||
|
{
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
this.structFeatManager = new WorldGenStructFeatManager(param.worldGenSettings, genLevel);
|
||||||
|
#elif MC_VER < MC_1_19_4
|
||||||
|
this.structFeatManager = new WorldGenStructFeatManager(param.worldGenSettings, genLevel, this.structCheck);
|
||||||
|
#else
|
||||||
|
this.structFeatManager = new WorldGenStructFeatManager(param.worldOptions, genLevel, this.structCheck);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_18_2
|
||||||
|
#elif MC_VER < MC_1_19_2
|
||||||
|
public void recreateStructureCheck()
|
||||||
|
{
|
||||||
|
if (previousGlobalWorldGenParams != null)
|
||||||
|
{
|
||||||
|
this.structCheck = this.createStructureCheck(previousGlobalWorldGenParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private StructureCheck createStructureCheck(GlobalWorldGenParams param)
|
||||||
|
{
|
||||||
|
return new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
||||||
|
param.mcServerLevel.dimension(), param.generator, this.level, param.generator.getBiomeSource(), param.worldSeed,
|
||||||
|
param.dataFixer);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
public void recreateStructureCheck() { /* do nothing */ }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+7
-7
@@ -1,7 +1,7 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
@@ -19,7 +19,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|||||||
public abstract class AbstractWorldGenStep
|
public abstract class AbstractWorldGenStep
|
||||||
{
|
{
|
||||||
public abstract void generateGroup(
|
public abstract void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers);
|
ArrayGridList<ChunkWrapper> chunkWrappers);
|
||||||
|
|
||||||
public abstract ChunkStatus getChunkStatus();
|
public abstract ChunkStatus getChunkStatus();
|
||||||
@@ -27,26 +27,26 @@ public abstract class AbstractWorldGenStep
|
|||||||
|
|
||||||
|
|
||||||
/** @return the list of chunks that have an earlier status and can be generated */
|
/** @return the list of chunks that have an earlier status and can be generated */
|
||||||
protected ArrayList<ChunkAccess> getChunksToGenerate(List<ChunkWrapper> chunkWrappers)
|
protected ArrayList<ChunkWrapper> getChunkWrappersToGenerate(List<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
ArrayList<ChunkAccess> chunksToGenerate = new ArrayList<>();
|
ArrayList<ChunkWrapper> chunkWrappersToGenerate = new ArrayList<>(chunkWrappers.size());
|
||||||
|
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunkWrapper.getStatus().isOrAfter(this.getChunkStatus()))
|
if (chunkWrapper.getStatus().isOrAfter(this.getChunkStatus()))
|
||||||
{
|
{
|
||||||
// this chunk has already generated this step
|
// this chunk has already been generated up to this step
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (chunk instanceof ProtoChunk)
|
else if (chunk instanceof ProtoChunk)
|
||||||
{
|
{
|
||||||
chunkWrapper.trySetStatus(this.getChunkStatus());
|
chunkWrapper.trySetStatus(this.getChunkStatus());
|
||||||
chunksToGenerate.add(chunk);
|
chunkWrappersToGenerate.add(chunkWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunksToGenerate;
|
return chunkWrappersToGenerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+21
-20
@@ -23,13 +23,11 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
@@ -66,47 +64,50 @@ public final class StepBiomes extends AbstractWorldGenStep
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateGroup(
|
public void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
ArrayList<ChunkAccess> chunksToDo = this.getChunksToGenerate(chunkWrappers);
|
ArrayList<ChunkWrapper> chunksToDo = this.getChunkWrappersToGenerate(chunkWrappers);
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
for (ChunkWrapper chunkWrapper : chunksToDo)
|
||||||
{
|
{
|
||||||
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
this.environment.params.generator.createBiomes(this.environment.params.biomes, chunk);
|
this.environment.globalParams.generator.createBiomes(this.environment.globalParams.biomes, chunk);
|
||||||
#elif MC_VER < MC_1_19_2
|
#elif MC_VER < MC_1_19_2
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.createBiomes(
|
this.environment.globalParams.generator.createBiomes(
|
||||||
this.environment.params.biomes,
|
this.environment.globalParams.biomes,
|
||||||
Runnable::run,
|
Runnable::run,
|
||||||
Blender.of(worldGenRegion),
|
Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk)
|
chunk)
|
||||||
);
|
);
|
||||||
#elif MC_VER < MC_1_19_4
|
#elif MC_VER < MC_1_19_4
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.createBiomes(
|
this.environment.globalParams.generator.createBiomes(
|
||||||
this.environment.params.biomes,
|
this.environment.globalParams.biomes,
|
||||||
Runnable::run,
|
Runnable::run,
|
||||||
this.environment.params.randomState, Blender.of(worldGenRegion),
|
this.environment.globalParams.randomState, Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk)
|
chunk)
|
||||||
);
|
);
|
||||||
#elif MC_VER < MC_1_21_1
|
#elif MC_VER < MC_1_21_1
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.createBiomes(
|
this.environment.globalParams.generator.createBiomes(
|
||||||
Runnable::run,
|
Runnable::run,
|
||||||
this.environment.params.randomState,
|
this.environment.globalParams.randomState,
|
||||||
Blender.of(worldGenRegion),
|
Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk)
|
chunk)
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.createBiomes(
|
this.environment.globalParams.generator.createBiomes(
|
||||||
this.environment.params.randomState,
|
this.environment.globalParams.randomState,
|
||||||
Blender.of(worldGenRegion),
|
Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk)
|
chunk)
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+9
-17
@@ -21,15 +21,14 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
|
||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
@@ -37,12 +36,13 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
|||||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
|
|
||||||
|
|
||||||
public final class StepFeatures extends AbstractWorldGenStep
|
public final class StepFeatures extends AbstractWorldGenStep
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
public static final ChunkStatus STATUS = ChunkStatus.FEATURES;
|
public static final ChunkStatus STATUS = ChunkStatus.FEATURES;
|
||||||
|
|
||||||
@@ -67,32 +67,24 @@ public final class StepFeatures extends AbstractWorldGenStep
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateGroup(
|
public void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
ArrayList<ChunkWrapper> chunksToDo = this.getChunkWrappersToGenerate(chunkWrappers);
|
||||||
|
for (ChunkWrapper chunkWrapper : chunksToDo)
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
|
||||||
{
|
|
||||||
// this chunk has already generated this step
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (chunk instanceof ProtoChunk)
|
|
||||||
{
|
|
||||||
chunkWrapper.trySetStatus(STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
worldGenRegion.setOverrideCenter(chunk.getPos());
|
worldGenRegion.setOverrideCenter(chunk.getPos());
|
||||||
environment.params.generator.applyBiomeDecoration(worldGenRegion, tParams.structFeat);
|
environment.globalParams.generator.applyBiomeDecoration(worldGenRegion, tParams.structFeatManager);
|
||||||
#else
|
#else
|
||||||
if (worldGenRegion.hasChunk(chunkWrapper.getChunkPos().getX(), chunkWrapper.getChunkPos().getZ()))
|
if (worldGenRegion.hasChunk(chunkWrapper.getChunkPos().getX(), chunkWrapper.getChunkPos().getZ()))
|
||||||
{
|
{
|
||||||
this.environment.params.generator.applyBiomeDecoration(worldGenRegion, chunk, tParams.structFeat.forWorldGenRegion(worldGenRegion));
|
this.environment.globalParams.generator.applyBiomeDecoration(worldGenRegion, chunk, tParams.structFeatManager.forWorldGenRegion(worldGenRegion));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+16
-31
@@ -20,18 +20,14 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
|
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
import net.minecraft.world.level.levelgen.blending.Blender;
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
@@ -68,56 +64,45 @@ public final class StepNoise extends AbstractWorldGenStep
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateGroup(
|
public void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
ArrayList<ChunkWrapper> chunksToDo = this.getChunkWrappersToGenerate(chunkWrappers);
|
||||||
|
for (ChunkWrapper chunkWrapper : chunksToDo)
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
chunkWrapper.trySetStatus(STATUS);
|
|
||||||
chunksToDo.add(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
|
||||||
{
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
this.environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
|
this.environment.globalParams.generator.fillFromNoise(worldGenRegion, tParams.structFeatManager, chunk);
|
||||||
#elif MC_VER < MC_1_18_2
|
#elif MC_VER < MC_1_18_2
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.fillFromNoise(
|
this.environment.globalParams.generator.fillFromNoise(
|
||||||
Runnable::run,
|
Runnable::run,
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk));
|
chunk));
|
||||||
#elif MC_VER < MC_1_19_2
|
#elif MC_VER < MC_1_19_2
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.fillFromNoise(
|
this.environment.globalParams.generator.fillFromNoise(
|
||||||
Runnable::run,
|
Runnable::run,
|
||||||
Blender.of(worldGenRegion),
|
Blender.of(worldGenRegion),
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk));
|
chunk));
|
||||||
#elif MC_VER < MC_1_21_1
|
#elif MC_VER < MC_1_21_1
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.fillFromNoise(
|
this.environment.globalParams.generator.fillFromNoise(
|
||||||
Runnable::run,
|
Runnable::run,
|
||||||
Blender.of(worldGenRegion),
|
Blender.of(worldGenRegion),
|
||||||
this.environment.params.randomState,
|
this.environment.globalParams.randomState,
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk));
|
chunk));
|
||||||
#else
|
#else
|
||||||
chunk = this.environment.confirmFutureWasRunSynchronously(
|
chunk = this.environment.confirmFutureWasRunSynchronously(
|
||||||
this.environment.params.generator.fillFromNoise(
|
this.environment.globalParams.generator.fillFromNoise(
|
||||||
Blender.of(worldGenRegion),
|
Blender.of(worldGenRegion),
|
||||||
this.environment.params.randomState,
|
this.environment.globalParams.randomState,
|
||||||
tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
tParams.structFeatManager.forWorldGenRegion(worldGenRegion),
|
||||||
chunk));
|
chunk));
|
||||||
#endif
|
#endif
|
||||||
UncheckedInterruptedException.throwIfInterrupted();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-24
@@ -20,17 +20,14 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
@@ -64,30 +61,14 @@ public final class StepStructureReference extends AbstractWorldGenStep
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateGroup(
|
public void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
ArrayList<ChunkWrapper> chunksToDo = this.getChunkWrappersToGenerate(chunkWrappers);
|
||||||
|
for (ChunkWrapper chunkWrapper : chunksToDo)
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
this.environment.globalParams.generator.createReferences(worldGenRegion, tParams.structFeatManager.forWorldGenRegion(worldGenRegion), chunk);
|
||||||
{
|
|
||||||
// this chunk has already generated this step
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (chunk instanceof ProtoChunk)
|
|
||||||
{
|
|
||||||
chunkWrapper.trySetStatus(STATUS);
|
|
||||||
chunksToDo.add(chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
|
||||||
{
|
|
||||||
// System.out.println("StepStructureReference: "+chunk.getPos());
|
|
||||||
this.environment.params.generator.createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+60
-59
@@ -20,22 +20,17 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
@@ -46,7 +41,7 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
|||||||
|
|
||||||
public final class StepStructureStart extends AbstractWorldGenStep
|
public final class StepStructureStart extends AbstractWorldGenStep
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
|
private static final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
|
||||||
private static final ReentrantLock STRUCTURE_PLACEMENT_LOCK = new ReentrantLock();
|
private static final ReentrantLock STRUCTURE_PLACEMENT_LOCK = new ReentrantLock();
|
||||||
|
|
||||||
@@ -71,74 +66,80 @@ public final class StepStructureStart extends AbstractWorldGenStep
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateGroup(
|
public void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
ArrayList<ChunkAccess> chunksToDo = this.getChunksToGenerate(chunkWrappers);
|
ArrayList<ChunkWrapper> chunksToDo = this.getChunkWrappersToGenerate(chunkWrappers);
|
||||||
|
|
||||||
|
// TODO should be put in wrapped environment so we can skip some other world gen steps
|
||||||
|
// SURFACE wouldn't need structure generation either
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
if (this.environment.params.worldGenSettings.generateFeatures())
|
if (!this.environment.globalParams.worldGenSettings.generateFeatures())
|
||||||
{
|
|
||||||
#elif MC_VER < MC_1_19_4
|
#elif MC_VER < MC_1_19_4
|
||||||
if (this.environment.params.worldGenSettings.generateStructures())
|
if (!this.environment.globalParams.worldGenSettings.generateStructures())
|
||||||
{
|
|
||||||
#else
|
#else
|
||||||
if (this.environment.params.worldOptions.generateStructures())
|
if (!this.environment.globalParams.worldOptions.generateStructures())
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (ChunkWrapper chunkWrapper : chunksToDo)
|
||||||
|
{
|
||||||
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
|
|
||||||
|
// hopefully this shouldn't cause any performance issues (this step is generally quite quick so hopefully it should be fine)
|
||||||
|
// and should prevent some concurrency issues
|
||||||
|
STRUCTURE_PLACEMENT_LOCK.lock();
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_19_2
|
||||||
|
this.environment.globalParams.generator.createStructures(this.environment.globalParams.registry, tParams.structFeatManager, chunk, this.environment.globalParams.structures,
|
||||||
|
this.environment.globalParams.worldSeed);
|
||||||
|
#elif MC_VER < MC_1_19_4
|
||||||
|
this.environment.globalParams.generator.createStructures(this.environment.globalParams.registry, this.environment.globalParams.randomState, tParams.structFeatManager, chunk, this.environment.globalParams.structures,
|
||||||
|
this.environment.globalParams.worldSeed);
|
||||||
|
#elif MC_VER <= MC_1_21_3
|
||||||
|
this.environment.globalParams.generator.createStructures(this.environment.globalParams.registry,
|
||||||
|
this.environment.globalParams.mcServerLevel.getChunkSource().getGeneratorState(),
|
||||||
|
tParams.structFeatManager, chunk, this.environment.globalParams.structures);
|
||||||
|
#else
|
||||||
|
this.environment.globalParams.generator.createStructures(this.environment.globalParams.registry,
|
||||||
|
this.environment.globalParams.mcServerLevel.getChunkSource().getGeneratorState(),
|
||||||
|
tParams.structFeatManager, chunk, this.environment.globalParams.structures,
|
||||||
|
this.environment.globalParams.mcServerLevel.dimension());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_18_2
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// hopefully this shouldn't cause any performance issues (this step is generally quite quick so hopefully it should be fine)
|
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
||||||
// and should prevent some concurrency issues
|
}
|
||||||
STRUCTURE_PLACEMENT_LOCK.lock();
|
catch (ArrayIndexOutOfBoundsException firstEx)
|
||||||
|
{
|
||||||
|
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
|
||||||
|
// This means the structFeat is corrupted (For some reason) and I need to reset it.
|
||||||
|
// TODO: Figure out in the future why this happens even though I am using new structFeat - OLD
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
// reset the structureStart
|
||||||
this.environment.params.generator.createStructures(this.environment.params.registry, tParams.structFeat, chunk, this.environment.params.structures,
|
tParams.recreateStructureCheck();
|
||||||
this.environment.params.worldSeed);
|
|
||||||
#elif MC_VER < MC_1_19_4
|
|
||||||
this.environment.params.generator.createStructures(this.environment.params.registry, this.environment.params.randomState, tParams.structFeat, chunk, this.environment.params.structures,
|
|
||||||
this.environment.params.worldSeed);
|
|
||||||
#elif MC_VER <= MC_1_21_3
|
|
||||||
this.environment.params.generator.createStructures(this.environment.params.registry,
|
|
||||||
this.environment.params.level.getChunkSource().getGeneratorState(),
|
|
||||||
tParams.structFeat, chunk, this.environment.params.structures);
|
|
||||||
#else
|
|
||||||
this.environment.params.generator.createStructures(this.environment.params.registry,
|
|
||||||
this.environment.params.level.getChunkSource().getGeneratorState(),
|
|
||||||
tParams.structFeat, chunk, this.environment.params.structures,
|
|
||||||
this.environment.params.level.dimension());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// try running the structure logic again
|
||||||
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
||||||
}
|
}
|
||||||
catch (ArrayIndexOutOfBoundsException firstEx)
|
catch (ArrayIndexOutOfBoundsException secondEx)
|
||||||
{
|
{
|
||||||
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
|
// the structure logic failed again, log it and move on
|
||||||
// This means the structFeat is corrupted (For some reason) and I need to reset it.
|
LOGGER.error("Unable to create structure starts for " + chunk.getPos() + ". This is an error with MC's world generation. Ignoring and continuing generation. Error: " + secondEx.getMessage()); // don't log the full stack trace since it is long and will generally end up in MC's code
|
||||||
// TODO: Figure out in the future why this happens even though I am using new structFeat - OLD
|
|
||||||
|
|
||||||
// reset the structureStart
|
|
||||||
tParams.recreateStructureCheck();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// try running the structure logic again
|
|
||||||
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
|
||||||
}
|
|
||||||
catch (ArrayIndexOutOfBoundsException secondEx)
|
|
||||||
{
|
|
||||||
// the structure logic failed again, log it and move on
|
|
||||||
LOGGER.error("Unable to create structure starts for " + chunk.getPos() + ". This is an error with MC's world generation. Ignoring and continuing generation. Error: " + secondEx.getMessage()); // don't log the full stack trace since it is long and will generally end up in MC's code
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
STRUCTURE_PLACEMENT_LOCK.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STRUCTURE_PLACEMENT_LOCK.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-26
@@ -20,17 +20,14 @@
|
|||||||
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
|
||||||
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
import com.seibel.distanthorizons.core.util.gridList.ArrayGridList;
|
||||||
import net.minecraft.server.level.WorldGenRegion;
|
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
|
||||||
|
|
||||||
#if MC_VER <= MC_1_20_4
|
#if MC_VER <= MC_1_20_4
|
||||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
@@ -64,37 +61,24 @@ public final class StepSurface extends AbstractWorldGenStep
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateGroup(
|
public void generateGroup(
|
||||||
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
|
ThreadWorldGenParams tParams, DhLitWorldGenRegion worldGenRegion,
|
||||||
ArrayGridList<ChunkWrapper> chunkWrappers)
|
ArrayGridList<ChunkWrapper> chunkWrappers)
|
||||||
{
|
{
|
||||||
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
|
ArrayList<ChunkWrapper> chunksToDo = this.getChunkWrappersToGenerate(chunkWrappers);
|
||||||
|
for (ChunkWrapper chunkWrapper : chunksToDo)
|
||||||
for (ChunkWrapper chunkWrapper : chunkWrappers)
|
|
||||||
{
|
{
|
||||||
ChunkAccess chunk = chunkWrapper.getChunk();
|
ChunkAccess chunk = chunkWrapper.getChunk();
|
||||||
if (chunkWrapper.getStatus().isOrAfter(STATUS))
|
|
||||||
{
|
|
||||||
// this chunk has already generated this step
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (chunk instanceof ProtoChunk)
|
|
||||||
{
|
|
||||||
chunkWrapper.trySetStatus(STATUS);
|
|
||||||
chunksToDo.add(chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ChunkAccess chunk : chunksToDo)
|
|
||||||
{
|
|
||||||
// System.out.println("StepSurface: "+chunk.getPos());
|
|
||||||
#if MC_VER < MC_1_18_2
|
#if MC_VER < MC_1_18_2
|
||||||
environment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
|
this.environment.globalParams.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
|
||||||
#elif MC_VER < MC_1_19_2
|
#elif MC_VER < MC_1_19_2
|
||||||
environment.params.generator.buildSurface(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
|
this.environment.globalParams.generator.buildSurface(worldGenRegion, tParams.structFeatManager.forWorldGenRegion(worldGenRegion), chunk);
|
||||||
#else
|
#else
|
||||||
environment.params.generator.buildSurface(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), environment.params.randomState, chunk);
|
this.environment.globalParams.generator.buildSurface(worldGenRegion, tParams.structFeatManager.forWorldGenRegion(worldGenRegion), this.environment.globalParams.randomState, chunk);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,6 @@ accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chu
|
|||||||
# used for grabbing vanilla rendered chunks
|
# used for grabbing vanilla rendered chunks
|
||||||
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
|
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
|
||||||
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
||||||
#accessible field net/minecraft/world/entity/Entity blockPosition Lnet/minecraft/core/BlockPos;
|
|
||||||
|
|
||||||
# lighting
|
# lighting
|
||||||
accessible field net/minecraft/client/renderer/LightTexture lightPixels Lcom/mojang/blaze3d/platform/NativeImage;
|
accessible field net/minecraft/client/renderer/LightTexture lightPixels Lcom/mojang/blaze3d/platform/NativeImage;
|
||||||
@@ -30,8 +29,6 @@ accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine L
|
|||||||
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
|
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
|
||||||
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
|
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
|
||||||
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
|
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
|
||||||
#accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
|
|
||||||
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
|
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
||||||
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
|
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
|
||||||
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine L
|
|||||||
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
|
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
|
||||||
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
|
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
|
||||||
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
|
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
|
||||||
# accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
|
|
||||||
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
|
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
||||||
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
|
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
|
||||||
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
|
|||||||
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
||||||
|
|
||||||
# world generation
|
# world generation
|
||||||
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
|
||||||
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecr
|
|||||||
# used for grabbing vanilla rendered chunks
|
# used for grabbing vanilla rendered chunks
|
||||||
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
#accessible method net/minecraft/client/renderer/LevelRenderer renderSectionLayer (Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V
|
|
||||||
|
|
||||||
# world generation
|
# world generation
|
||||||
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
|
||||||
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecr
|
|||||||
# used for grabbing vanilla rendered chunks
|
# used for grabbing vanilla rendered chunks
|
||||||
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
#accessible method net/minecraft/client/renderer/LevelRenderer renderSectionLayer (Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V
|
|
||||||
|
|
||||||
# world generation
|
# world generation
|
||||||
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
|
||||||
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ accessible field net/minecraft/client/renderer/LevelRenderer level Lnet/minecraf
|
|||||||
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
# world generation
|
# world generation
|
||||||
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
|
||||||
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
accessWidener v1 named
|
||||||
|
|
||||||
|
# used when determining where to save files to
|
||||||
|
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/nio/file/Path;
|
||||||
|
# used to help determine what folder a clientLevel is
|
||||||
|
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
|
||||||
|
|
||||||
|
# used when rendering
|
||||||
|
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F
|
||||||
|
accessible field net/minecraft/client/Minecraft deltaTracker Lnet/minecraft/client/DeltaTracker$Timer;
|
||||||
|
accessible field net/minecraft/client/renderer/LevelRenderer level Lnet/minecraft/client/multiplayer/ClientLevel;
|
||||||
|
|
||||||
|
|
||||||
|
# used for grabbing vanilla rendered chunks
|
||||||
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
|
# world generation
|
||||||
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
|
||||||
|
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
||||||
|
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
|
||||||
|
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
|
||||||
|
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
|
||||||
|
|
||||||
|
# getting existing chunks outside the main thread
|
||||||
|
accessible method net/minecraft/server/level/ChunkMap getVisibleChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
|
||||||
|
|
||||||
|
# lod generation from save file
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/SimpleRegionStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/IOWorker storage Lnet/minecraft/world/level/chunk/storage/RegionFileStorage;
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage regionCache Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;
|
||||||
|
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage folder Ljava/nio/file/Path;
|
||||||
|
|
||||||
|
# grabbing textures
|
||||||
|
accessible class net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture
|
||||||
|
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameX (I)I
|
||||||
|
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameY (I)I
|
||||||
|
accessible field net/minecraft/client/renderer/texture/SpriteContents animatedTexture Lnet/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture;
|
||||||
|
accessible field net/minecraft/client/renderer/texture/SpriteContents originalImage Lcom/mojang/blaze3d/platform/NativeImage;
|
||||||
|
|
||||||
|
# UI stuff
|
||||||
|
accessible field net/minecraft/client/gui/components/AbstractButton SPRITES Lnet/minecraft/client/gui/components/WidgetSprites;
|
||||||
|
# Handles inserting the config button
|
||||||
|
accessible field net/minecraft/client/gui/layouts/HeaderAndFooterLayout headerFrame Lnet/minecraft/client/gui/layouts/FrameLayout;
|
||||||
|
accessible field net/minecraft/client/gui/layouts/FrameLayout children Ljava/util/List;
|
||||||
|
accessible class net/minecraft/client/gui/layouts/FrameLayout$ChildContainer
|
||||||
|
accessible field net/minecraft/client/gui/layouts/LinearLayout wrapped Lnet/minecraft/client/gui/layouts/GridLayout;
|
||||||
|
accessible method net/minecraft/client/gui/components/debug/DebugScreenEntries register (Ljava/lang/String;Lnet/minecraft/client/gui/components/debug/DebugScreenEntry;)Lnet/minecraft/resources/Identifier;
|
||||||
|
|
||||||
|
# hacky stuff
|
||||||
|
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||||
|
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ accessible field net/minecraft/client/Minecraft deltaTracker Lnet/minecraft/clie
|
|||||||
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
# world generation
|
# world generation
|
||||||
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
|
||||||
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ accessible field net/minecraft/client/Minecraft deltaTracker Lnet/minecraft/clie
|
|||||||
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
|
||||||
|
|
||||||
# world generation
|
# world generation
|
||||||
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
|
||||||
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
|
||||||
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
|
||||||
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
|
||||||
|
|||||||
+1
-1
Submodule coreSubProjects updated: ba2681d7b2...eb2317934f
+6
-4
@@ -19,7 +19,9 @@ loom {
|
|||||||
"-Dminecraft.api.session.host=https://nope.invalid",
|
"-Dminecraft.api.session.host=https://nope.invalid",
|
||||||
"-Dminecraft.api.services.host=https://nope.invalid",
|
"-Dminecraft.api.services.host=https://nope.invalid",
|
||||||
// https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
|
// https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
|
||||||
"-Dio.netty.leakDetection.level=advanced"
|
"-Dio.netty.leakDetection.level=advanced",
|
||||||
|
"-XX:+UseZGC",
|
||||||
|
"-XX:+ZGenerational"
|
||||||
)
|
)
|
||||||
programArgs("--username", "Dev")
|
programArgs("--username", "Dev")
|
||||||
}
|
}
|
||||||
@@ -76,11 +78,11 @@ dependencies {
|
|||||||
// Fabric API
|
// Fabric API
|
||||||
addModJar(fabricApi.module("fabric-api-base", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-api-base", rootProject.fabric_api_version))
|
||||||
addModJar(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version))
|
||||||
if (buildVersionBefore(minecraft_version, "1.21.10"))
|
if (buildVersionBefore(minecraft_version, "1.21.9"))
|
||||||
{
|
{
|
||||||
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
||||||
}
|
}
|
||||||
else // > 1.21.10
|
else // > 1.21.9
|
||||||
{
|
{
|
||||||
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version))
|
||||||
addModJar(fabricApi.module("fabric-resource-loader-v1", rootProject.fabric_api_version))
|
addModJar(fabricApi.module("fabric-resource-loader-v1", rootProject.fabric_api_version))
|
||||||
@@ -100,7 +102,7 @@ dependencies {
|
|||||||
|
|
||||||
|
|
||||||
// Mod Menu
|
// Mod Menu
|
||||||
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}")
|
addMod("com.terraformersmc:modmenu:${rootProject.modmenu_version}", rootProject.enable_mod_menu)
|
||||||
|
|
||||||
// Starlight
|
// Starlight
|
||||||
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
|
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ import java.nio.FloatBuffer;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.concurrent.AbstractExecutorService;
|
import java.util.concurrent.AbstractExecutorService;
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
|||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import net.minecraft.world.phys.HitResult;
|
import net.minecraft.world.phys.HitResult;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,7 +85,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
private final ClientApi clientApi = ClientApi.INSTANCE;
|
private final ClientApi clientApi = ClientApi.INSTANCE;
|
||||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
// TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi
|
// TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi
|
||||||
private static final int[] KEY_TO_CHECK_FOR = { GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8, GLFW.GLFW_KEY_P};
|
private static final int[] KEY_TO_CHECK_FOR = { GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8, GLFW.GLFW_KEY_P};
|
||||||
@@ -113,14 +113,6 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
|
||||||
// tick events //
|
|
||||||
//=============//
|
|
||||||
|
|
||||||
ClientTickEvents.START_CLIENT_TICK.register((client) -> { ClientApi.INSTANCE.clientTickEvent(); });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
// chunk events //
|
// chunk events //
|
||||||
//==============//
|
//==============//
|
||||||
@@ -130,8 +122,16 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
{
|
{
|
||||||
if (MC.clientConnectedToDedicatedServer())
|
if (MC.clientConnectedToDedicatedServer())
|
||||||
{
|
{
|
||||||
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
|
// executor to prevent locking up the render/event thread
|
||||||
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
|
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
|
if (executor != null)
|
||||||
|
{
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
|
||||||
|
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -145,8 +145,6 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ()))
|
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ()))
|
||||||
{
|
{
|
||||||
// executor to prevent locking up the render/event thread
|
// executor to prevent locking up the render/event thread
|
||||||
// if the getChunk() takes longer than expected
|
|
||||||
// (which can be caused by certain mods)
|
|
||||||
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
if (executor != null)
|
if (executor != null)
|
||||||
{
|
{
|
||||||
@@ -185,8 +183,6 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ()))
|
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ()))
|
||||||
{
|
{
|
||||||
// executor to prevent locking up the render/event thread
|
// executor to prevent locking up the render/event thread
|
||||||
// if the getChunk() takes longer than expected
|
|
||||||
// (which can be caused by certain mods)
|
|
||||||
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
if (executor != null)
|
if (executor != null)
|
||||||
{
|
{
|
||||||
@@ -219,8 +215,8 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// render event //
|
// render event //
|
||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
// TODO wait for fabric to re-add their rendering API
|
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
WorldRenderEvents.AFTER_SETUP.register((renderContext) ->
|
WorldRenderEvents.AFTER_SETUP.register((renderContext) ->
|
||||||
{
|
{
|
||||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
|
||||||
|
|||||||
@@ -20,13 +20,12 @@
|
|||||||
package com.seibel.distanthorizons.fabric;
|
package com.seibel.distanthorizons.fabric;
|
||||||
|
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
|
|
||||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigBase;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.*;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.*;
|
||||||
@@ -38,10 +37,8 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
|
|||||||
import net.fabricmc.fabric.api.event.Event;
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.lwjgl.util.tinyfd.TinyFileDialogs;
|
|
||||||
|
|
||||||
#if MC_VER >= MC_1_19_2
|
#if MC_VER >= MC_1_19_2
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
@@ -49,8 +46,12 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
|||||||
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
import javax.swing.*;
|
#if MC_VER <= MC_1_21_10
|
||||||
import java.awt.*;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,22 +61,27 @@ import java.util.function.Consumer;
|
|||||||
*/
|
*/
|
||||||
public class FabricMain extends AbstractModInitializer implements ClientModInitializer, DedicatedServerModInitializer
|
public class FabricMain extends AbstractModInitializer implements ClientModInitializer, DedicatedServerModInitializer
|
||||||
{
|
{
|
||||||
#if MC_VER >= MC_1_21_1
|
#if MC_VER <= MC_1_20_6
|
||||||
|
private static final ResourceLocation INITIAL_PHASE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
|
||||||
|
#elif MC_VER <= MC_1_21_10
|
||||||
private static final ResourceLocation INITIAL_PHASE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
|
private static final ResourceLocation INITIAL_PHASE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
|
||||||
#else
|
#else
|
||||||
private static final ResourceLocation INITIAL_PHASE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
|
private static final Identifier INITIAL_PHASE = Identifier.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.DEDICATED_SERVER_INITIAL_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createInitialBindings()
|
protected void createInitialSharedBindings()
|
||||||
{
|
{
|
||||||
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
|
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||||
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new FabricPluginPacketSender());
|
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new FabricPluginPacketSender());
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
protected void createInitialClientBindings() { /* no additional setup needed currently */ }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IEventProxy createClientProxy() { return new FabricClientProxy(); }
|
protected IEventProxy createClientProxy() { return new FabricClientProxy(); }
|
||||||
@@ -97,7 +103,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
|||||||
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
|
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
|
||||||
LOGGER.fatal(indiumMissingMessage);
|
LOGGER.fatal(indiumMissingMessage);
|
||||||
|
|
||||||
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, indiumMissingMessage, "ok", "error", false);
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, indiumMissingMessage, "ok", "error");
|
||||||
|
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
String errorMessage = "loading Distant Horizons. Distant Horizons requires Indium in order to run with Sodium.";
|
String errorMessage = "loading Distant Horizons. Distant Horizons requires Indium in order to run with Sodium.";
|
||||||
@@ -109,6 +115,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
|||||||
this.tryCreateModCompatAccessor("starlight", IStarlightAccessor.class, StarlightAccessor::new);
|
this.tryCreateModCompatAccessor("starlight", IStarlightAccessor.class, StarlightAccessor::new);
|
||||||
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
|
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
|
||||||
this.tryCreateModCompatAccessor("bclib", IBCLibAccessor.class, BCLibAccessor::new);
|
this.tryCreateModCompatAccessor("bclib", IBCLibAccessor.class, BCLibAccessor::new);
|
||||||
|
this.tryCreateModCompatAccessor("c2me", IC2meAccessor.class, C2meAccessor::new);
|
||||||
#if MC_VER >= MC_1_19_4
|
#if MC_VER >= MC_1_19_4
|
||||||
// 1.19.4 is the lowest version Iris supports DH
|
// 1.19.4 is the lowest version Iris supports DH
|
||||||
this.tryCreateModCompatAccessor("iris", IIrisAccessor.class, IrisAccessor::new);
|
this.tryCreateModCompatAccessor("iris", IIrisAccessor.class, IrisAccessor::new);
|
||||||
@@ -153,11 +160,6 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
|
|||||||
ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class).setFogOcclusion(false);
|
ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class).setFogOcclusion(false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ConfigBase.INSTANCE == null)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Config was not initialized. Make sure to call LodCommonMain.initConfig() before calling this method.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import net.minecraft.client.gui.screens.TitleScreen;
|
|||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_20_6
|
#if MC_VER >= MC_1_20_6
|
||||||
import com.seibel.distanthorizons.common.CommonPacketPayload;
|
import com.seibel.distanthorizons.common.CommonPacketPayload;
|
||||||
@@ -52,7 +52,7 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
private static final ServerApi SERVER_API = ServerApi.INSTANCE;
|
private static final ServerApi SERVER_API = ServerApi.INSTANCE;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
private final boolean isDedicatedServer;
|
private final boolean isDedicatedServer;
|
||||||
|
|
||||||
@@ -93,10 +93,6 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
|
|
||||||
/* Register the mod needed event callbacks */
|
/* Register the mod needed event callbacks */
|
||||||
|
|
||||||
// ServerTickEvent
|
|
||||||
ServerTickEvents.END_SERVER_TICK.register((server) -> SERVER_API.serverTickEvent());
|
|
||||||
|
|
||||||
|
|
||||||
// can be enabled to test overrides/events without having to build a separate API project
|
// can be enabled to test overrides/events without having to build a separate API project
|
||||||
if (false)
|
if (false)
|
||||||
{
|
{
|
||||||
|
|||||||
+14
-2
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.fabric.mixins.client;
|
package com.seibel.distanthorizons.fabric.mixins.client;
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||||||
public class MixinChunkSectionsToRender
|
public class MixinChunkSectionsToRender
|
||||||
{ /* rendering before was handled via Fabric API events */ }
|
{ /* rendering before was handled via Fabric API events */ }
|
||||||
#else
|
#else
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
@@ -38,15 +38,27 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.textures.GpuSampler;
|
||||||
|
#endif
|
||||||
|
|
||||||
@Mixin(ChunkSectionsToRender.class)
|
@Mixin(ChunkSectionsToRender.class)
|
||||||
public class MixinChunkSectionsToRender
|
public class MixinChunkSectionsToRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
// needs to fire at HEAD with a lower than normal order (less than 1000)
|
// needs to fire at HEAD with a lower than normal order (less than 1000)
|
||||||
// otherwise it will be canceled by Sodium
|
// otherwise it will be canceled by Sodium
|
||||||
@Inject(at = @At("HEAD"), method = "renderGroup", order = 800)
|
@Inject(at = @At("HEAD"), method = "renderGroup", order = 800)
|
||||||
private void renderDeferredLayer(ChunkSectionLayerGroup chunkSectionLayerGroup, CallbackInfo ci)
|
private void renderDeferredLayer(ChunkSectionLayerGroup chunkSectionLayerGroup, CallbackInfo ci)
|
||||||
|
#else
|
||||||
|
// needs to fire at HEAD with a lower than normal order (less than 1000)
|
||||||
|
// otherwise it will be canceled by Sodium
|
||||||
|
@Inject(at = @At("HEAD"), method = "renderGroup", order = 800)
|
||||||
|
private void renderDeferredLayer(ChunkSectionLayerGroup chunkSectionLayerGroup, GpuSampler gpuSampler, CallbackInfo ci)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, Minecraft.getInstance().levelRenderer.level);
|
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, Minecraft.getInstance().levelRenderer.level);
|
||||||
|
|
||||||
|
|||||||
+22
-2
@@ -3,8 +3,10 @@ package com.seibel.distanthorizons.fabric.mixins.client;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
@@ -16,6 +18,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
|
||||||
|
import java.util.concurrent.AbstractExecutorService;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@Mixin(ClientPacketListener.class)
|
@Mixin(ClientPacketListener.class)
|
||||||
@@ -45,8 +49,24 @@ public class MixinClientPacketListener
|
|||||||
@Inject(method = "enableChunkLight", at = @At("TAIL"))
|
@Inject(method = "enableChunkLight", at = @At("TAIL"))
|
||||||
void onEnableChunkLight(LevelChunk chunk, int x, int z, CallbackInfo ci)
|
void onEnableChunkLight(LevelChunk chunk, int x, int z, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
IClientLevelWrapper clientLevel = ClientLevelWrapper.getWrapper((ClientLevel) chunk.getLevel());
|
if (chunk == null)
|
||||||
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, clientLevel), clientLevel);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// executor to prevent locking up the render thread
|
||||||
|
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
|
if (executor == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
IClientLevelWrapper clientLevel = ClientLevelWrapper.getWrapper((ClientLevel) this.level);
|
||||||
|
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, clientLevel), clientLevel);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import java.util.List;
|
|||||||
@Mixin(DebugScreenOverlay.class)
|
@Mixin(DebugScreenOverlay.class)
|
||||||
public class MixinDebugScreenOverlay
|
public class MixinDebugScreenOverlay
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
@Inject(method = "getSystemInformation", at = @At("RETURN"))
|
@Inject(method = "getSystemInformation", at = @At("RETURN"))
|
||||||
private void addCustomF3(CallbackInfoReturnable<List<String>> cir)
|
private void addCustomF3(CallbackInfoReturnable<List<String>> cir)
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-1
@@ -160,9 +160,12 @@ public class MixinFogRenderer
|
|||||||
{
|
{
|
||||||
#if MC_VER < MC_1_21_6
|
#if MC_VER < MC_1_21_6
|
||||||
Entity entity = camera.getEntity();
|
Entity entity = camera.getEntity();
|
||||||
|
#elif MC_VER <= MC_1_21_10
|
||||||
|
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||||
|
Entity entity = camera.getEntity();
|
||||||
#else
|
#else
|
||||||
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
|
||||||
Entity entity = camera.getEntity();
|
Entity entity = camera.entity();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -30,7 +30,7 @@ import net.minecraft.client.renderer.RenderType;
|
|||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
#elif MC_VER < MC_1_21_10
|
#elif MC_VER < MC_1_21_9
|
||||||
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
|
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
|
||||||
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
|
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
|
||||||
@@ -77,7 +77,7 @@ import org.spongepowered.asm.mixin.Unique;
|
|||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ public class MixinLevelRenderer
|
|||||||
private ClientLevel level;
|
private ClientLevel level;
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
@@ -116,7 +116,7 @@ public class MixinLevelRenderer
|
|||||||
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
method = "Lnet/minecraft/client/renderer/LevelRenderer;renderSectionLayer(Lnet/minecraft/client/renderer/RenderType;DDDLorg/joml/Matrix4f;Lorg/joml/Matrix4f;)V",
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback)
|
private void renderChunkLayer(RenderType renderType, double x, double y, double z, Matrix4f projectionMatrix, Matrix4f frustumMatrix, CallbackInfo callback)
|
||||||
#elif MC_VER < MC_1_21_10
|
#elif MC_VER < MC_1_21_9
|
||||||
@Inject(at = @At("HEAD"), method = "prepareChunkRenders", cancellable = true)
|
@Inject(at = @At("HEAD"), method = "prepareChunkRenders", cancellable = true)
|
||||||
private void prepareChunkRenders(Matrix4fc projectionMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
private void prepareChunkRenders(Matrix4fc projectionMatrix, double d, double e, double f, CallbackInfoReturnable<ChunkSectionsToRender> callback)
|
||||||
#else
|
#else
|
||||||
@@ -141,7 +141,7 @@ public class MixinLevelRenderer
|
|||||||
// get the matrices directly from MC
|
// get the matrices directly from MC
|
||||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||||
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
ClientApi.RENDER_STATE.mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
#elif MC_VER < MC_1_21_10
|
#elif MC_VER < MC_1_21_9
|
||||||
// MC combined the model view and projection matricies
|
// MC combined the model view and projection matricies
|
||||||
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
ClientApi.RENDER_STATE.mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f();
|
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f();
|
||||||
@@ -169,7 +169,7 @@ public class MixinLevelRenderer
|
|||||||
{
|
{
|
||||||
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
ClientApi.INSTANCE.renderDeferredLodsForShaders();
|
||||||
}
|
}
|
||||||
#elif MC_VER < MC_1_21_10
|
#elif MC_VER < MC_1_21_9
|
||||||
// rendering handled via Fabric Api render event
|
// rendering handled via Fabric Api render event
|
||||||
#else
|
#else
|
||||||
// handled here and in MixinChunkSectionsToRender
|
// handled here and in MixinChunkSectionsToRender
|
||||||
@@ -178,7 +178,7 @@ public class MixinLevelRenderer
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_10
|
#if MC_VER < MC_1_21_9
|
||||||
// rendering handled via Fabric Api render event
|
// rendering handled via Fabric Api render event
|
||||||
#else
|
#else
|
||||||
@Inject(at = @At("HEAD"), method = "prepareChunkRenders")
|
@Inject(at = @At("HEAD"), method = "prepareChunkRenders")
|
||||||
|
|||||||
+19
-6
@@ -29,6 +29,7 @@ import net.minecraft.client.renderer.LightTexture;
|
|||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
@@ -61,28 +62,40 @@ public class MixinLightTexture
|
|||||||
private GpuTexture texture;
|
private GpuTexture texture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private MinecraftRenderWrapper renderWrapper = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
|
||||||
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
public void updateLightTexture(float partialTicks, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
if (mc == null || mc.getWrappedClientLevel() == null)
|
if (mc == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
|
||||||
MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
if (clientLevel == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lazy initialization to make sure we don't call this too early
|
||||||
|
if (this.renderWrapper == null)
|
||||||
|
{
|
||||||
|
this.renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
renderWrapper.updateLightmap(this.lightPixels, clientLevel);
|
this.renderWrapper.updateLightmap(this.lightPixels, clientLevel);
|
||||||
#elif MC_VER < MC_1_21_5
|
#elif MC_VER < MC_1_21_5
|
||||||
renderWrapper.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
this.renderWrapper.setLightmapId(this.target.getColorTextureId(), clientLevel);
|
||||||
#else
|
#else
|
||||||
GlTexture glTexture = (GlTexture) this.texture;
|
GlTexture glTexture = (GlTexture) this.texture;
|
||||||
renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
|
this.renderWrapper.setLightmapId(glTexture.glId(), clientLevel);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -16,7 +16,7 @@ import net.minecraft.client.gui.screens.Screen;
|
|||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screens.TitleScreen;
|
import net.minecraft.client.gui.screens.TitleScreen;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
@@ -34,7 +34,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
public abstract class MixinMinecraft
|
public abstract class MixinMinecraft
|
||||||
{
|
{
|
||||||
@Unique
|
@Unique
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MixinMinecraft.class.getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
|
|||||||
+14
-7
@@ -28,7 +28,6 @@ import net.minecraft.network.chat.Component;
|
|||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
#endif
|
#endif
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -51,6 +50,11 @@ import net.minecraft.client.gui.screens.OptionsScreen;
|
|||||||
import net.minecraft.client.gui.screens.options.OptionsScreen;
|
import net.minecraft.client.gui.screens.options.OptionsScreen;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a button to the menu to goto the config
|
* Adds a button to the menu to goto the config
|
||||||
@@ -62,13 +66,16 @@ import net.minecraft.client.gui.screens.options.OptionsScreen;
|
|||||||
public class MixinOptionsScreen extends Screen
|
public class MixinOptionsScreen extends Screen
|
||||||
{
|
{
|
||||||
/** Texture used for the config opening button */
|
/** Texture used for the config opening button */
|
||||||
|
#if MC_VER <= MC_1_20_6
|
||||||
@Unique
|
@Unique
|
||||||
private static final ResourceLocation ICON_TEXTURE =
|
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
||||||
#if MC_VER < MC_1_21_1
|
#elif MC_VER <= MC_1_21_10
|
||||||
new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
|
@Unique
|
||||||
#else
|
private static final ResourceLocation ICON_TEXTURE = ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
|
||||||
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
|
#else
|
||||||
#endif
|
@Unique
|
||||||
|
private static final Identifier ICON_TEXTURE = Identifier.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
|
|||||||
+2
-9
@@ -13,8 +13,7 @@ public class MixinLevelTicks<T>
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
|
||||||
import net.minecraft.world.ticks.LevelTicks;
|
import net.minecraft.world.ticks.LevelTicks;
|
||||||
import net.minecraft.world.ticks.ScheduledTick;
|
import net.minecraft.world.ticks.ScheduledTick;
|
||||||
|
|
||||||
@@ -26,18 +25,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
|
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
|
||||||
public class MixinLevelTicks<T>
|
public class MixinLevelTicks<T>
|
||||||
{
|
{
|
||||||
// TODO put in a common location
|
|
||||||
private static boolean isWorldGenThread()
|
|
||||||
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
|
||||||
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
|
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
|
||||||
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
|
||||||
if (isWorldGenThread())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-8
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.fabric.mixins.server;
|
package com.seibel.distanthorizons.fabric.mixins.server;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
@@ -35,10 +36,8 @@ public class MixinTracingExecutor
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
|
||||||
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
|
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
|
||||||
import net.minecraft.TracingExecutor;
|
import net.minecraft.TracingExecutor;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
@@ -55,16 +54,11 @@ import java.util.concurrent.Executor;
|
|||||||
@Mixin(TracingExecutor.class)
|
@Mixin(TracingExecutor.class)
|
||||||
public class MixinTracingExecutor
|
public class MixinTracingExecutor
|
||||||
{
|
{
|
||||||
// TODO put in a common location
|
|
||||||
private static boolean isWorldGenThread()
|
|
||||||
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
|
|
||||||
|
|
||||||
|
|
||||||
// replaced with TracingExecutor in MC 1.21.3+
|
// replaced with TracingExecutor in MC 1.21.3+
|
||||||
@Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
|
||||||
private void forName(String executorName, CallbackInfoReturnable<Executor> ci)
|
private void forName(String executorName, CallbackInfoReturnable<Executor> ci)
|
||||||
{
|
{
|
||||||
if (isWorldGenThread())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
// run this task on the current DH thread instead of a new MC thread
|
// run this task on the current DH thread instead of a new MC thread
|
||||||
ci.setReturnValue(new RunOnThisThreadExecutorService());
|
ci.setReturnValue(new RunOnThisThreadExecutorService());
|
||||||
|
|||||||
+12
-12
@@ -19,19 +19,23 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.fabric.mixins.server;
|
package com.seibel.distanthorizons.fabric.mixins.server;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
|
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.Util;
|
||||||
|
#else
|
||||||
|
import net.minecraft.util.Util;
|
||||||
|
#endif
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_16_5
|
#if MC_VER < MC_1_16_5
|
||||||
#elif MC_VER < MC_1_21_3
|
#elif MC_VER < MC_1_21_3
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
@@ -46,15 +50,11 @@ import java.util.function.Supplier;
|
|||||||
@Mixin(Util.class)
|
@Mixin(Util.class)
|
||||||
public class MixinUtilBackgroundThread
|
public class MixinUtilBackgroundThread
|
||||||
{
|
{
|
||||||
private static boolean isWorldGenThread()
|
|
||||||
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
|
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_21_3
|
#if MC_VER < MC_1_21_3
|
||||||
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
|
||||||
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
|
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
|
||||||
{
|
{
|
||||||
if (isWorldGenThread())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
// run this task on the current DH thread instead of a new MC thread
|
// run this task on the current DH thread instead of a new MC thread
|
||||||
ci.setReturnValue(new RunOnThisThreadExecutorService());
|
ci.setReturnValue(new RunOnThisThreadExecutorService());
|
||||||
@@ -70,7 +70,7 @@ public class MixinUtilBackgroundThread
|
|||||||
at = @At("HEAD"), cancellable = true)
|
at = @At("HEAD"), cancellable = true)
|
||||||
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
|
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
|
||||||
{
|
{
|
||||||
if (isWorldGenThread())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
||||||
ci.setReturnValue(r);
|
ci.setReturnValue(r);
|
||||||
@@ -86,7 +86,7 @@ public class MixinUtilBackgroundThread
|
|||||||
at = @At("HEAD"), cancellable = true)
|
at = @At("HEAD"), cancellable = true)
|
||||||
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
|
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
|
||||||
{
|
{
|
||||||
if (isWorldGenThread())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
|
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
|
||||||
ci.setReturnValue(r);
|
ci.setReturnValue(r);
|
||||||
|
|||||||
+2
-2
@@ -5,13 +5,13 @@ import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
|
|||||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkProcessingEvent;
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkProcessingEvent;
|
||||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class TestChunkInputReplacerEvent extends DhApiChunkProcessingEvent
|
public class TestChunkInputReplacerEvent extends DhApiChunkProcessingEvent
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
private static final String REPLACEMENT_BLOCK_STATE_NAMESPACE = "minecraft:stone";
|
private static final String REPLACEMENT_BLOCK_STATE_NAMESPACE = "minecraft:stone";
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@ import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -23,7 +23,7 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
public class TestGenericWorldGenerator implements IDhApiWorldGenerator
|
public class TestGenericWorldGenerator implements IDhApiWorldGenerator
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
private final IDhApiLevelWrapper levelWrapper;
|
private final IDhApiLevelWrapper levelWrapper;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -6,12 +6,12 @@ import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelLo
|
|||||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
// TODO add to API example once Builderb0y has given the all-clear
|
// TODO add to API example once Builderb0y has given the all-clear
|
||||||
public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
|
public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLevelLoad(DhApiEventParam<DhApiLevelLoadEvent.EventParam> event)
|
public void onLevelLoad(DhApiEventParam<DhApiLevelLoadEvent.EventParam> event)
|
||||||
|
|||||||
+1
-3
@@ -23,9 +23,7 @@ import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
|||||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
|
|
||||||
/**
|
/** For making the config show up in modmenu */
|
||||||
* For making the config show up in modmenu
|
|
||||||
*/
|
|
||||||
public class ModMenuIntegration implements ModMenuApi
|
public class ModMenuIntegration implements ModMenuApi
|
||||||
{
|
{
|
||||||
// For the custom config code
|
// For the custom config code
|
||||||
|
|||||||
+8
-12
@@ -17,20 +17,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.seibel.distanthorizons.common.wrappers;
|
package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IC2meAccessor;
|
||||||
|
|
||||||
public class DependencySetupDoneCheck
|
public class C2meAccessor implements IC2meAccessor
|
||||||
{
|
{
|
||||||
// TODO move to DependencySetup
|
@Override
|
||||||
public static boolean isDone = false;
|
public String getModName()
|
||||||
/**
|
{
|
||||||
* This is used so we can override some MC logic when running
|
return "c2me";
|
||||||
* in DH's world generator.
|
}
|
||||||
* Specifically so we can redirect threads to run on DH threads instead
|
|
||||||
* of MC threads.
|
|
||||||
*/
|
|
||||||
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> { return false; });
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
-12
@@ -34,22 +34,14 @@ import net.irisshaders.iris.api.v0.IrisApi;
|
|||||||
public class IrisAccessor implements IIrisAccessor
|
public class IrisAccessor implements IIrisAccessor
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public String getModName()
|
public String getModName() { return Iris.MODID; }
|
||||||
{
|
|
||||||
return Iris.MODID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isShaderPackInUse()
|
public boolean isShaderPackInUse() { return IrisApi.getInstance().isShaderPackInUse(); }
|
||||||
{
|
|
||||||
return IrisApi.getInstance().isShaderPackInUse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRenderingShadowPass()
|
public boolean isRenderingShadowPass() { return IrisApi.getInstance().isRenderingShadowPass(); }
|
||||||
{
|
|
||||||
return IrisApi.getInstance().isRenderingShadowPass();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-4
@@ -28,9 +28,6 @@ public class OptifineAccessor extends AbstractOptifineAccessor
|
|||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getModName()
|
public String getModName() { return "Optifine-Fabric"; }
|
||||||
{
|
|
||||||
return "Optifine-Fabric-1.18.X";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -26,6 +26,7 @@ import java.lang.invoke.MethodType;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_20_1
|
#if MC_VER < MC_1_20_1
|
||||||
@@ -50,9 +51,11 @@ public class SodiumAccessor implements ISodiumAccessor
|
|||||||
*/
|
*/
|
||||||
public static final boolean isSodiumV5OrLess;
|
public static final boolean isSodiumV5OrLess;
|
||||||
|
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER <= MC_1_19_4
|
||||||
|
#elif MC_VER <= MC_1_21_10
|
||||||
private static MethodHandle setFogOcclusionMethod;
|
private static MethodHandle setFogOcclusionMethod;
|
||||||
private static Object sodiumPerformanceOptions;
|
private static Object sodiumPerformanceOptions;
|
||||||
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -78,7 +81,8 @@ public class SodiumAccessor implements ISodiumAccessor
|
|||||||
@Override
|
@Override
|
||||||
public void setFogOcclusion(boolean occlusionEnabled)
|
public void setFogOcclusion(boolean occlusionEnabled)
|
||||||
{
|
{
|
||||||
#if MC_VER >= MC_1_20_1
|
#if MC_VER <= MC_1_19_4
|
||||||
|
#elif MC_VER <= MC_1_21_10
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (sodiumPerformanceOptions == null)
|
if (sodiumPerformanceOptions == null)
|
||||||
@@ -122,6 +126,8 @@ public class SodiumAccessor implements ISodiumAccessor
|
|||||||
{
|
{
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// in newer versions of Sodium this doesn't appear to be an issue so it can probably just be ignored
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
|||||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
{
|
{
|
||||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
private static final ForgePluginPacketSender PACKET_SENDER = (ForgePluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
private static final ForgePluginPacketSender PACKET_SENDER = (ForgePluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
#if MC_VER < MC_1_19_2
|
#if MC_VER < MC_1_19_2
|
||||||
@@ -107,21 +107,6 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
|
||||||
// tick events //
|
|
||||||
//=============//
|
|
||||||
|
|
||||||
@SubscribeEvent
|
|
||||||
public void clientTickEvent(TickEvent.ClientTickEvent event)
|
|
||||||
{
|
|
||||||
if (event.phase == TickEvent.Phase.START)
|
|
||||||
{
|
|
||||||
ClientApi.INSTANCE.clientTickEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
// world events //
|
// world events //
|
||||||
//==============//
|
//==============//
|
||||||
|
|||||||
@@ -22,17 +22,16 @@ package com.seibel.distanthorizons.forge;
|
|||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
import com.seibel.distanthorizons.common.AbstractModInitializer;
|
||||||
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
||||||
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.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.forge.wrappers.modAccessor.ModChecker;
|
import com.seibel.distanthorizons.forge.wrappers.modAccessor.ModChecker;
|
||||||
import com.seibel.distanthorizons.forge.wrappers.modAccessor.OptifineAccessor;
|
import com.seibel.distanthorizons.forge.wrappers.modAccessor.OptifineAccessor;
|
||||||
|
import com.seibel.distanthorizons.forge.wrappers.modAccessor.OculusAccessor;
|
||||||
|
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
@@ -86,11 +85,13 @@ public class ForgeMain extends AbstractModInitializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createInitialBindings()
|
protected void createInitialSharedBindings()
|
||||||
{
|
{
|
||||||
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
|
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||||
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new ForgePluginPacketSender());
|
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new ForgePluginPacketSender());
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
protected void createInitialClientBindings() { /* no additional setup needed currently */ }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IEventProxy createClientProxy() { return new ForgeClientProxy(); }
|
protected IEventProxy createClientProxy() { return new ForgeClientProxy(); }
|
||||||
@@ -102,6 +103,7 @@ public class ForgeMain extends AbstractModInitializer
|
|||||||
protected void initializeModCompat()
|
protected void initializeModCompat()
|
||||||
{
|
{
|
||||||
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
|
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
|
||||||
|
this.tryCreateModCompatAccessor("oculus", IIrisAccessor.class, OculusAccessor::new);
|
||||||
|
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY,
|
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import net.minecraftforge.event.server.ServerStoppingEvent;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -90,16 +90,6 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
|
|||||||
// events //
|
// events //
|
||||||
//========//
|
//========//
|
||||||
|
|
||||||
// ServerTickEvent (at end)
|
|
||||||
@SubscribeEvent
|
|
||||||
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
|
||||||
{
|
|
||||||
if (event.phase == TickEvent.Phase.END)
|
|
||||||
{
|
|
||||||
this.serverApi.serverTickEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerWorldLoadEvent
|
// ServerWorldLoadEvent
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void dedicatedWorldLoadEvent(#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 FMLServerAboutToStartEvent #else ServerAboutToStartEvent #endif event)
|
public void dedicatedWorldLoadEvent(#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 FMLServerAboutToStartEvent #else ServerAboutToStartEvent #endif event)
|
||||||
|
|||||||
+5
-3
@@ -67,9 +67,11 @@ public class MixinFogRenderer
|
|||||||
|
|
||||||
Entity entity = camera.getEntity();
|
Entity entity = camera.getEntity();
|
||||||
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
|
||||||
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
|
if (!isSpecialFog
|
||||||
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
|
&& cameraNotInFluid
|
||||||
&& Config.Client.Advanced.Graphics.Fog.disableVanillaFog.get())
|
&& fogMode == FogMode.FOG_TERRAIN
|
||||||
|
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
|
||||||
|
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
|
||||||
{
|
{
|
||||||
#if MC_VER < MC_1_17_1
|
#if MC_VER < MC_1_17_1
|
||||||
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
|||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.client.gui.screens.TitleScreen;
|
import net.minecraft.client.gui.screens.TitleScreen;
|
||||||
import org.apache.logging.log4j.Logger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -29,7 +29,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
public class MixinMinecraft
|
public class MixinMinecraft
|
||||||
{
|
{
|
||||||
@Unique
|
@Unique
|
||||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MixinMinecraft.class.getSimpleName());
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+15
-11
@@ -22,12 +22,15 @@ package com.seibel.distanthorizons.forge.mixins.server;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
|
|
||||||
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
|
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
@@ -35,17 +38,17 @@ import net.minecraft.Util;
|
|||||||
@Mixin(Util.class)
|
@Mixin(Util.class)
|
||||||
public class MixinUtilBackgroundThread
|
public class MixinUtilBackgroundThread
|
||||||
{
|
{
|
||||||
private static boolean shouldApplyOverride()
|
@Unique
|
||||||
{
|
private static final DhLogger LOGGER = new DhLoggerBuilder().name("MixinUtilBackgroundThread").build();
|
||||||
return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
|
||||||
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
|
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
|
||||||
{
|
{
|
||||||
if (shouldApplyOverride())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
//ApiShared.LOGGER.info("util backgroundExecutor triggered");
|
//LOGGER.info("util backgroundExecutor triggered");
|
||||||
ci.setReturnValue(new RunOnThisThreadExecutorService());
|
ci.setReturnValue(new RunOnThisThreadExecutorService());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,21 +58,22 @@ public class MixinUtilBackgroundThread
|
|||||||
at = @At("HEAD"), cancellable = true)
|
at = @At("HEAD"), cancellable = true)
|
||||||
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
|
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
|
||||||
{
|
{
|
||||||
if (shouldApplyOverride())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
//LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
||||||
ci.setReturnValue(r);
|
ci.setReturnValue(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MC_VER >= MC_1_18_2
|
#if MC_VER >= MC_1_18_2
|
||||||
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
|
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
|
||||||
at = @At("HEAD"), cancellable = true)
|
at = @At("HEAD"), cancellable = true)
|
||||||
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
|
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
|
||||||
{
|
{
|
||||||
if (shouldApplyOverride())
|
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
|
||||||
{
|
{
|
||||||
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
|
//LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
|
||||||
ci.setReturnValue(r);
|
ci.setReturnValue(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.forge.wrappers.modAccessor;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModName()
|
||||||
|
{
|
||||||
|
return "oculus";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShaderPackInUse()
|
||||||
|
{
|
||||||
|
// assume shaders are always active
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRenderingShadowPass()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"server.MixinUtilBackgroundThread",
|
"server.MixinUtilBackgroundThread",
|
||||||
"server.MixinChunkGenerator",
|
"server.MixinChunkGenerator",
|
||||||
"server.MixinTFChunkGenerator",
|
"server.MixinTFChunkGenerator",
|
||||||
"server.MixinChunkMap",
|
"server.MixinChunkMap",
|
||||||
"server.MixinServerPlayer",
|
"server.MixinServerPlayer",
|
||||||
"server.MixinEntity"
|
"server.MixinEntity"
|
||||||
],
|
],
|
||||||
|
|||||||
+5
-4
@@ -5,8 +5,8 @@ org.gradle.caching=true
|
|||||||
|
|
||||||
# Mod Info
|
# Mod Info
|
||||||
mod_name=DistantHorizons
|
mod_name=DistantHorizons
|
||||||
mod_version=2.3.5-b
|
mod_version=2.4.5-b
|
||||||
api_version=4.1.0
|
api_version=5.1.0
|
||||||
maven_group=com.seibel.distanthorizons
|
maven_group=com.seibel.distanthorizons
|
||||||
mod_readable_name=Distant Horizons
|
mod_readable_name=Distant Horizons
|
||||||
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.
|
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.
|
||||||
@@ -18,11 +18,12 @@ mod_issues=https://gitlab.com/jeseibel/distant-horizons/-/issues
|
|||||||
mod_discord=https://discord.gg/xAB8G4cENx
|
mod_discord=https://discord.gg/xAB8G4cENx
|
||||||
|
|
||||||
# Global Plugin Versions
|
# Global Plugin Versions
|
||||||
manifold_version=2025.1.27
|
manifold_version=2025.1.28
|
||||||
# 2023.1.17 can be used if there are mystery Java compiler issues
|
# 2023.1.17 can be used if there are mystery Java compiler issues
|
||||||
nightconfig_version=3.6.6
|
nightconfig_version=3.6.6
|
||||||
lz4_version=1.8.0
|
lz4_version=1.8.0
|
||||||
xz_version=1.9
|
xz_version=1.9
|
||||||
|
zstd_version=1.5.7-6
|
||||||
# Before updating, read relocate_natives/README.md
|
# Before updating, read relocate_natives/README.md
|
||||||
sqlite_jdbc_version=3.47.2.0
|
sqlite_jdbc_version=3.47.2.0
|
||||||
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
# 8.2.1 is the newest version we can use since that's the version MC 1.16.5 uses
|
||||||
@@ -54,7 +55,7 @@ versionStr=
|
|||||||
|
|
||||||
# This defines what MC version Intellij will use for the preprocessor
|
# This defines what MC version Intellij will use for the preprocessor
|
||||||
# and what version is used automatically by build and run commands
|
# and what version is used automatically by build and run commands
|
||||||
mcVer=1.21.10
|
mcVer=1.21.11
|
||||||
|
|
||||||
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
|
||||||
#minecraftMemoryJavaArg="-Xmx4G"
|
#minecraftMemoryJavaArg="-Xmx4G"
|
||||||
|
|||||||
@@ -65,7 +65,10 @@ dependencies {
|
|||||||
|
|
||||||
// Neoforge
|
// Neoforge
|
||||||
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
||||||
addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft)
|
|
||||||
|
// Iris
|
||||||
|
addMod("maven.modrinth:iris:${rootProject.neo_iris_version}", rootProject.neo_enable_iris)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user