Compare commits

...

69 Commits

Author SHA1 Message Date
s809 d360402bc3 Add correct descriptions 2026-01-18 22:38:06 +05:00
s809 6c56d09b18 Split off server generation into a separate toggle 2026-01-17 01:43:18 +05:00
s809 2716059840 Make sure payload chunk is readable 2026-01-14 22:17:50 +05:00
James Seibel a60887e9a7 Dynamically get beacon base blocks in MC 1.18.2+ 2026-01-10 17:33:51 -06:00
James Seibel 1b6c5a451a Improve concurrent iterating in QuadTree 2026-01-10 17:03:48 -06:00
James Seibel 4e91911e58 Add extra error logging around getCloudColor() 2026-01-10 16:21:17 -06:00
James Seibel bfae194919 remove unused broken import 2026-01-10 16:02:05 -06:00
James Seibel e562b2fdca Fix farmland color (fixes #690) 2026-01-10 12:47:34 -06:00
James Seibel 47fa6d7d8b minor ui reformat 2026-01-10 11:57:01 -06:00
James Seibel 053d1333ca Fix opening DH in forge mod menu (Fixes #678)
Done to fix a forge limitation where logos can't contain a file pathhttps://github.com/MinecraftForge/MinecraftForge/issues/7348
2026-01-10 11:56:39 -06:00
James Seibel 961c4190ad Fix Fabric debug keys 2026-01-10 10:31:56 -06:00
James Seibel 2f2ac0859c let shift click go back in UI options 2026-01-10 10:28:24 -06:00
James Seibel b59781b064 Fix white water/tinting with BCLib 2026-01-10 09:22:57 -06:00
s809 39cc5bb8aa Fix compilation 2026-01-09 21:01:15 +05:00
s809 abdbc73865 Reapply "Run plugin messages on a DH thread" 2026-01-09 20:29:40 +05:00
James Seibel 596f9f834a expand distant beacon beams for visiblity 2026-01-07 07:50:34 -06:00
James Seibel 8f2aaf4ef4 Fix #1152 (beacon beam going through tinted glass) 2026-01-07 07:50:01 -06:00
James Seibel 2320740a4a Change EMinecraftColor -> MinecraftTextFormat 2026-01-06 07:11:04 -06:00
James Seibel 4f0dc07995 Minor refactoring after slab color fix merge 2026-01-05 07:48:34 -06:00
James Seibel 336a9a94c8 Merge Slab Color Fix 2026-01-05 07:45:24 -06:00
James Seibel 1158496d9d increase fabric version in 1.20.1 to latest 2026-01-05 07:38:43 -06:00
s809 84479ed48c Wrong message target 2026-01-04 20:04:34 +05:00
s809 0c71ca96c6 Add a chat message for incompatible messages 2026-01-04 19:34:58 +05:00
s809 43dff26063 Replace the failure state with future exceptions 2025-12-27 00:51:35 +05:00
James Seibel 3cba883ba2 up version number 2.4.5 -> 2.4.6-dev 2025-12-24 22:41:36 -06:00
James Seibel 2d2e7524ae up version number 2.4.4 -> 2.4.5 2025-12-24 22:06:59 -06:00
James Seibel e8ff7abaea Replace MC color code strings with an enum 2025-12-24 22:05:59 -06:00
James Seibel 008ad52bbc remove dev from version number 2025-12-23 22:57:10 -06:00
James Seibel d0b44a1ffc Fix toggling world gen not recreating queue 2025-12-23 22:57:05 -06:00
James Seibel 4ffe430686 up DH api version 5.0.0 -> 5.1.0 2025-12-23 20:01:19 -06:00
James Seibel 19ca97c6c1 add experimental option to ignore rendering dimensions by name 2025-12-23 12:22:05 -06:00
James Seibel 3334394bfd Fix earth curvature shader compiling 2025-12-23 08:47:50 -06:00
James Seibel 180e7cd814 change forge fog config to match neo/fabric 2025-12-22 20:32:41 -06:00
James Seibel 84cf4505f2 merge world gen refactor 2025-12-20 10:54:07 -06:00
James Seibel 1d74eea3ef reduce stuttering at the cost of lighting quality 2025-12-20 10:53:14 -06:00
James Seibel 6ee2e6be25 up manifold version 25.1.27 -> 25.1.28 2025-12-19 16:55:32 -06:00
James Seibel b5c47d67cb up version number 2.4.3 -> 2.4.4-dev 2025-12-18 10:04:57 -06:00
James Seibel ead59d0817 remove dev from version number 2025-12-18 09:35:57 -06:00
James Seibel 1c9229c8f1 Fix 1.21.11 stuttering when flying into new chunks in singleplayer 2025-12-18 09:35:54 -06:00
James Seibel 968a14c6a5 remove chunkWrapper.isStillValid() 2025-12-18 09:35:21 -06:00
ada_aster 5608db9c56 Slab Block Color Fix 2025-12-17 22:12:15 -05:00
ada_aster 81b6a25805 Slab Block Color Fix 2025-12-17 22:08:45 -05:00
ada_aster 276d90b3e6 Slab Block Color Fix 2025-12-17 21:48:31 -05:00
James Seibel 851c7439d5 Fix GLProxy error in multiplayer 2025-12-17 09:02:15 -06:00
s809 c902357a8f Update core 2025-12-17 00:17:27 +05:00
s809 63170078f5 Fix returning wrong dimension name 2025-12-17 00:17:21 +05:00
James Seibel d0dd1f125b ignore chunk update events during all world gen pos 2025-12-15 15:07:01 -06:00
James Seibel 32950d793e slight light engine optimization 2025-12-15 14:37:22 -06:00
James Seibel 54e9bad907 up version number 2.4.2 -> 2.4.3-dev 2025-12-15 10:17:34 -06:00
James Seibel bb4ac770bd remove dev from version number 2025-12-15 09:49:23 -06:00
James Seibel 16afada6e9 Fix inconsistency with server/client wrapper dim names 2025-12-15 09:49:23 -06:00
James Seibel 7d0785a5fa Fix dimension names missing namespace for multiplayer folders 2025-12-15 08:56:08 -06:00
James Seibel 6a67df462b Move GC warning into the log 2025-12-15 08:44:12 -06:00
s809 0c45c76ff8 Use a different path for zstd natives 2025-12-15 11:21:28 +05:00
James Seibel bcb442e38d Improve initial library check error handling 2025-12-14 22:29:22 -06:00
James Seibel 977ae471ea Fix auto update success dialog 2025-12-14 21:51:00 -06:00
James Seibel b1701ab0d0 remove iris unsupported error for neo 1.21.11 2025-12-14 21:20:22 -06:00
James Seibel c048d5cb56 hide LODs when underwater 2025-12-14 17:22:40 -06:00
James Seibel 2702f742d6 up version number 2.4.1 -> 2.4.2-dev 2025-12-14 17:00:44 -06:00
James Seibel 7add025c8a remove dev from version number 2025-12-14 13:46:24 -06:00
James Seibel 9dc220feb2 re-generate ZStd relocated cache
The previous versions appeared to be out of date, causing linker errors
2025-12-13 21:32:15 -06:00
s809 79955252c9 Add zstd to relocated natives & update sqlite 2025-12-14 04:03:19 +05:00
James Seibel bf13cc48a3 Print a warning if G1GC is used 2025-12-13 16:47:03 -06:00
James Seibel cf454c80d7 add Zstd decompress lib check in initalizer 2025-12-13 15:48:09 -06:00
James Seibel e6404cd882 remove double ";" in ForgeMain 2025-12-13 15:44:40 -06:00
James Seibel 52e64dc403 log if a mod accessor isn't added 2025-12-13 15:44:27 -06:00
James Seibel 7c858afc5d add partial oculus support 2025-12-13 13:17:43 -06:00
James Seibel a44a5d7465 replace client ticks with a timer
Prevents DH loading issues when MC ticks are paused
2025-12-13 11:19:39 -06:00
James Seibel f2d373b779 up version number 2.4.0 -> 2.4.1-dev 2025-12-13 10:20:53 -06:00
48 changed files with 513 additions and 296 deletions
+39 -8
View File
@@ -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"
@@ -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)
@@ -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
@@ -14,6 +14,7 @@ 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.MinecraftTextFormat;
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;
@@ -26,7 +27,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import com.seibel.distanthorizons.core.logging.DhLogger; 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;
@@ -166,6 +166,10 @@ 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()
@@ -236,8 +240,7 @@ public abstract class AbstractModInitializer
if (showChatWarnings) if (showChatWarnings)
{ {
String message = String message =
// orange text MinecraftTextFormat.ORANGE + "Distant Horizons: Alex's Cave detected." + MinecraftTextFormat.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);
} }
@@ -259,8 +262,7 @@ public abstract class AbstractModInitializer
if (showChatWarnings) if (showChatWarnings)
{ {
String message = String message =
// orange text MinecraftTextFormat.ORANGE + "Distant Horizons: WWOO detected." + MinecraftTextFormat.CLEAR_FORMATTING + "\n" +
"\u00A76" + "Distant Horizons: WWOO detected." + "\u00A7r\n" +
wwooWarning; wwooWarning;
ClientApi.INSTANCE.showChatMessageNextFrame(message); ClientApi.INSTANCE.showChatMessageNextFrame(message);
} }
@@ -290,8 +292,7 @@ public abstract class AbstractModInitializer
if (showChatWarnings) if (showChatWarnings)
{ {
String message = String message =
// orange text MinecraftTextFormat.ORANGE + "Distant Horizons: Chunky detected." + MinecraftTextFormat.CLEAR_FORMATTING + "\n" +
"\u00A76" + "Distant Horizons: Chunky detected." + "\u00A7r\n" +
chunkyWarning; chunkyWarning;
ClientApi.INSTANCE.showChatMessageNextFrame(message); ClientApi.INSTANCE.showChatMessageNextFrame(message);
} }
@@ -41,6 +41,7 @@ import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -49,12 +50,14 @@ import net.minecraft.core.Registry;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.EmptyBlockGetter;
#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
import net.minecraft.tags.TagKey;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.EmptyBlockGetter;
#else #else
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@@ -88,6 +91,15 @@ public class BlockStateWrapper implements IBlockStateWrapper
public static final String DIRT_RESOURCE_LOCATION_STRING = "minecraft:dirt"; public static final String DIRT_RESOURCE_LOCATION_STRING = "minecraft:dirt";
public static final String WATER_RESOURCE_LOCATION_STRING = "minecraft:water"; public static final String WATER_RESOURCE_LOCATION_STRING = "minecraft:water";
/** Used to handle older MC versions that don't have an simple way of getting the block's tags */
public static final List<String> OLD_BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList(
"iron_block",
"gold_block",
"diamond_block",
"emerald_block",
"netherite_block"
);
public static HashSet<IBlockStateWrapper> rendererIgnoredBlocks = null; public static HashSet<IBlockStateWrapper> rendererIgnoredBlocks = null;
public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null; public static HashSet<IBlockStateWrapper> rendererIgnoredCaveBlocks = null;
@@ -176,11 +188,14 @@ public class BlockStateWrapper implements IBlockStateWrapper
String lowercaseSerial = this.serialString.toLowerCase(); String lowercaseSerial = this.serialString.toLowerCase();
// beacon blocks
// beacon base blocks
#if MC_VER <= MC_1_18_2
// Older MC versions are harder to get block tags, so just use a static list to determine beacon blocks
boolean isBeaconBaseBlock = false; boolean isBeaconBaseBlock = false;
for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++) for (int i = 0; i < OLD_BEACON_BASE_BLOCK_NAME_LIST.size(); i++)
{ {
String baseBlockName = LodUtil.BEACON_BASE_BLOCK_NAME_LIST.get(i); String baseBlockName = OLD_BEACON_BASE_BLOCK_NAME_LIST.get(i);
if (lowercaseSerial.contains(baseBlockName)) if (lowercaseSerial.contains(baseBlockName))
{ {
isBeaconBaseBlock = true; isBeaconBaseBlock = true;
@@ -188,8 +203,23 @@ public class BlockStateWrapper implements IBlockStateWrapper
} }
} }
this.isBeaconBaseBlock = isBeaconBaseBlock; this.isBeaconBaseBlock = isBeaconBaseBlock;
#else
if (blockState != null)
{
// check if this block has any tags
Stream<TagKey<Block>> tags = blockState.getTags();
this.isBeaconBaseBlock = tags.anyMatch((TagKey<Block> tag) -> tag.location().getPath().toLowerCase().contains("beacon_base_blocks"));
}
else
{
this.isBeaconBaseBlock = false;
}
#endif
// beacon block
this.isBeaconBlock = lowercaseSerial.contains("minecraft:beacon"); this.isBeaconBlock = lowercaseSerial.contains("minecraft:beacon");
// beacon tint color // beacon tint color
Color beaconTintColor = null; Color beaconTintColor = null;
if (this.blockState != null if (this.blockState != null
@@ -225,6 +255,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
// bedrock is a special case fully opaque block that does allow beacons through // bedrock is a special case fully opaque block that does allow beacons through
allowsBeaconBeamPassage = true; allowsBeaconBeamPassage = true;
} }
else if (lowercaseSerial.contains("minecraft:tinted_glass"))
{
// tinted glass is a special case where it isn't fully opaque,
// but should block beacons
allowsBeaconBeamPassage = false;
}
else if (propagatesSkyLightDown || !canOcclude) else if (propagatesSkyLightDown || !canOcclude)
{ {
// stairs, cake, fences, etc. // stairs, cake, fences, etc.
@@ -30,10 +30,7 @@ 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.block.Block; import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.RotatedPillarBlock;
#if MC_VER >= MC_1_19_2 #if MC_VER >= MC_1_19_2
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
#else #else
@@ -41,6 +38,7 @@ import java.util.Random;
#endif #endif
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import net.minecraft.world.level.block.state.properties.SlabType;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@@ -64,6 +62,8 @@ public class ClientBlockStateColorCache
{ {
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final Minecraft MC = Minecraft.getInstance();
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<>();
@@ -79,7 +79,16 @@ public class ClientBlockStateColorCache
/** This is the order each direction on a block is processed when attempting to get the texture/color */ /** This is the order each direction on a block is processed when attempting to get the texture/color */
private static final Direction[] COLOR_RESOLUTION_DIRECTION_ORDER = { Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN }; private static final @Nullable Direction[] COLOR_RESOLUTION_DIRECTION_ORDER =
{
Direction.UP,
null, // null represents "unculled" faces, IE the top of farmland
Direction.NORTH,
Direction.EAST,
Direction.WEST,
Direction.SOUTH,
Direction.DOWN
};
private static final int FLOWER_COLOR_SCALE = 5; private static final int FLOWER_COLOR_SCALE = 5;
@@ -281,14 +290,23 @@ public class ClientBlockStateColorCache
@Nullable @Nullable
private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction) private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction)
{ {
List<BakedQuad> quads = null; BlockState effectiveBlockState = this.blockState;
// if this block is a slab, use it's double variant so we can get the top face,
// otherwise the color will use the side, which isn't as accurate
if (this.blockState.getBlock() instanceof SlabBlock)
{
effectiveBlockState = this.blockState.setValue( SlabBlock.TYPE, SlabType.DOUBLE );
}
List<BakedQuad> quads;
#if MC_VER < MC_1_21_5 #if MC_VER < MC_1_21_5
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper(). quads = MC.getModelManager().getBlockModelShaper().
getBlockModel(this.blockState).getQuads(this.blockState, direction, RANDOM); getBlockModel(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM);
#else #else
List<BlockModelPart> blockModelPartList = Minecraft.getInstance().getModelManager().getBlockModelShaper(). List<BlockModelPart> blockModelPartList = MC.getModelManager().getBlockModelShaper().
getBlockModel(this.blockState).collectParts(RANDOM); getBlockModel(effectiveBlockState).collectParts(RANDOM);
quads = new ArrayList<>(); quads = new ArrayList<>();
if (blockModelPartList != null) if (blockModelPartList != null)
@@ -558,10 +576,22 @@ public class ClientBlockStateColorCache
static EColorMode getColorMode(Block block) static EColorMode getColorMode(Block block)
{ {
if (block instanceof LeavesBlock) return Leaves; if (block instanceof LeavesBlock)
if (block instanceof FlowerBlock) return Flower; {
if (block.toString().contains("glass")) return Glass; return Leaves;
if (block.toString().equals("Block{chiselsandbits:chiseled}")) return Chisel; }
if (block instanceof FlowerBlock)
{
return Flower;
}
if (block.toString().contains("glass"))
{
return Glass;
}
if (block.toString().equals("Block{chiselsandbits:chiseled}"))
{
return Chisel;
}
return Default; return Default;
} }
} }
@@ -51,10 +51,10 @@ public class TintGetterOverride extends AbstractDhTintGetter
public TintGetterOverride() { } public TintGetterOverride() { }
public void update(LevelReader parent, BiomeWrapper biomeWrapper, BlockStateWrapper blockStateWrapper, FullDataSourceV2 fullDataSource, IClientLevelWrapper clientLevelWrapper) public void update(BiomeWrapper biomeWrapper, BlockStateWrapper blockStateWrapper, FullDataSourceV2 fullDataSource, IClientLevelWrapper clientLevelWrapper)
{ {
super.update(biomeWrapper, blockStateWrapper, fullDataSource, clientLevelWrapper); super.update(biomeWrapper, blockStateWrapper, fullDataSource, clientLevelWrapper);
this.parent = parent; this.parent = (LevelReader)this.clientLevelWrapper.getWrappedMcObject();
} }
@@ -18,6 +18,7 @@
*/ */
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;
@@ -80,6 +81,8 @@ public class ChunkWrapper implements IChunkWrapper
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;
@@ -107,22 +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, wrappedLevel, true);
}
public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel, boolean recreateHeightmaps)
{ {
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);
if (recreateHeightmaps)
{
this.createDhHeightMaps();
}
} }
@Override
public ChunkWrapper copy() { return new ChunkWrapper(this.chunk, this.wrappedLevel); }
//=========// //=========//
@@ -242,11 +244,15 @@ 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(); }
@Override
public void createDhHeightMaps() 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; {
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.solidHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
@@ -614,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 //
//================// //================//
@@ -13,6 +13,7 @@ import java.util.regex.Pattern;
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.common.wrappers.gui.config.ConfigGuiInfo;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigHandler; import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.config.types.*; import com.seibel.distanthorizons.core.config.types.*;
@@ -26,6 +27,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
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;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@@ -59,6 +61,9 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
#endif #endif
import org.lwjgl.glfw.GLFW;
import com.mojang.blaze3d.platform.InputConstants;
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;
@@ -84,6 +89,8 @@ public class ClassicConfigGUI
public static final ConfigCoreInterface CONFIG_CORE_INTERFACE = new ConfigCoreInterface(); public static final ConfigCoreInterface CONFIG_CORE_INTERFACE = new ConfigCoreInterface();
private static final MinecraftClientWrapper MC_CLIENT = MinecraftClientWrapper.INSTANCE;
//==============// //==============//
@@ -175,36 +182,36 @@ public class ClassicConfigGUI
&& !ModInfo.IS_DEV_BUILD) && !ModInfo.IS_DEV_BUILD)
{ {
this.addBtn(new TexturedButtonWidget( this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen // Where the button is on the screen
this.width - 28, this.height - 28, this.width - 28, this.height - 28,
// Width and height of the button // Width and height of the button
20, 20, 20, 20,
// texture UV Offset // texture UV Offset
0, 0, 0, 0,
// Some texture stuff // Some texture stuff
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"),
#elif MC_VER <= MC_1_21_10 #elif MC_VER <= MC_1_21_10
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"), ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
#else #else
Identifier.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"), 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) -> { (buttonWidget) -> {
ChangelogScreen changelogScreen = new ChangelogScreen(this); ChangelogScreen changelogScreen = new ChangelogScreen(this);
if (changelogScreen.usable) if (changelogScreen.usable)
{ {
Objects.requireNonNull(this.minecraft).setScreen(changelogScreen); Objects.requireNonNull(this.minecraft).setScreen(changelogScreen);
} }
else else
{ {
LOGGER.warn("Changelog was not able to open"); LOGGER.warn("Changelog was not able to open");
} }
}, },
// Add a title to the button // Add a title to the button
Translatable(ModInfo.ID + ".updater.title") Translatable(ModInfo.ID + ".updater.title")
)); ));
} }
@@ -415,17 +422,25 @@ public class ClassicConfigGUI
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) enumConfigEntry.guiValue); final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) enumConfigEntry.guiValue);
Function<Object, Component> getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString()); Function<Object, Component> getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString());
configGuiInfo.buttonOptionMap = configGuiInfo.buttonOptionMap =
new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>( new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(
(button) -> (button) ->
{ {
// get the currently selected enum and enum index // get the currently selected enum and enum index
int startingIndex = enumList.indexOf(enumConfigEntry.get()); int startingIndex = enumList.indexOf(enumConfigEntry.get());
Enum<?> enumValue = enumList.get(startingIndex); Enum<?> enumValue = enumList.get(startingIndex);
// search for the next enum that is selectable boolean shiftPressed =
int index = startingIndex + 1; InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_LEFT_SHIFT)
|| InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_RIGHT_SHIFT);
// move forward or backwards depending on if the shift key is pressed
int index = shiftPressed ? startingIndex-1 : startingIndex+1;
index = (index >= enumList.size()) ? 0 : index; index = (index >= enumList.size()) ? 0 : index;
// walk through the enums to find the next selectable one
while (index != startingIndex) while (index != startingIndex)
{ {
enumValue = enumList.get(index); enumValue = enumList.get(index);
@@ -436,13 +451,24 @@ public class ClassicConfigGUI
break; break;
} }
index++; // move forward or backwards depending on if the shift key is pressed
index = (index >= enumList.size()) ? 0 : index; index = shiftPressed ? index-1 : index+1;
// wrap around to the other side of the array when necessary
if (index >= enumList.size())
{
index = 0;
}
else if (index < 0)
{
index = enumList.size() - 1;
}
} }
if (index == startingIndex) if (index == startingIndex)
{ {
// none of the enums should be selectable, this is a programmer error // one of the enums should be selectable, this is a programmer error
enumValue = enumList.get(startingIndex); 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 + "]."); LOGGER.warn("Enum [" + enumValue.getClass() + "] doesn't contain any values that should be selectable via the UI, sticking to the currently selected value [" + enumValue + "].");
} }
@@ -120,26 +120,26 @@ public class UpdateModScreen extends DhScreen
if (!ModInfo.IS_DEV_BUILD) if (!ModInfo.IS_DEV_BUILD)
{ {
this.addBtn(new TexturedButtonWidget( this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen // Where the button is on the screen
this.width / 2 - 97, this.height / 2 + 8, this.width / 2 - 97, this.height / 2 + 8,
// Width and height of the button // Width and height of the button
20, 20, 20, 20,
// Offset // Offset
0, 0, 0, 0,
// Some textuary stuff // Some textuary stuff
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"),
#elif MC_VER <= MC_1_21_10 #elif MC_VER <= MC_1_21_10
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"), ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
#else #else
Identifier.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"), 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(this.minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), (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")
)); ));
} }
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
import java.io.File; import java.io.File;
import com.mojang.blaze3d.platform.Window;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
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;
@@ -203,19 +204,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
return; return;
} }
if (!GLProxy.hasInstance())
{
// rendering setup hasn't finished
return;
}
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
player.sendMessage(new TextComponent(string), getPlayer().getUUID()); player.sendMessage(new TextComponent(string), getPlayer().getUUID());
#elif MC_VER < MC_1_21_9 #elif MC_VER < MC_1_21_9
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false); player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
#else #else
GLProxy.getInstance().queueRunningOnRenderThread(() -> GLProxy.queueRunningOnRenderThread(() ->
{ {
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false); player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
}); });
@@ -268,6 +263,24 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
// misc // // misc //
//======// //======//
/**
* no override and not included in {@link IMinecraftClientWrapper}
* since this would only be used in common/client, not core.
*/
public
#if MC_VER < MC_1_21_9 long
#else Window
#endif
getGlfwWindowId()
{
#if MC_VER < MC_1_21_9
long glfwWindowId = MINECRAFT.getWindow().getWindow();
return glfwWindowId;
#else
return MINECRAFT.getWindow();
#endif
}
@Override @Override
public IProfilerWrapper getProfiler() public IProfilerWrapper getProfiler()
{ {
@@ -293,7 +306,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@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);
@@ -77,6 +77,8 @@ public class ClientLevelWrapper implements IClientLevelWrapper
private final Function<BlockState, ClientBlockStateColorCache> createCachedBlockColorCacheFunc = (blockState) -> new ClientBlockStateColorCache(blockState, this); private final Function<BlockState, ClientBlockStateColorCache> createCachedBlockColorCacheFunc = (blockState) -> new ClientBlockStateColorCache(blockState, this);
private boolean cloudColorFailLogged = false;
private BlockStateWrapper dirtBlockWrapper; private BlockStateWrapper dirtBlockWrapper;
private IDhLevel dhLevel; private IDhLevel dhLevel;
@@ -259,7 +261,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
return this.level.dimension().location().toString(); return this.level.dimension().location().toString();
#else #else
return this.level.dimension().identifier().getPath(); return this.level.dimension().identifier().toString();
#endif #endif
} }
@@ -295,23 +297,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 @Override
public ClientLevel getWrappedMcObject() { return this.level; } public ClientLevel getWrappedMcObject() { return this.level; }
@@ -360,14 +345,68 @@ public class ClientLevelWrapper implements IClientLevelWrapper
public Color getCloudColor(float tickDelta) public Color getCloudColor(float tickDelta)
{ {
#if MC_VER < MC_1_21_3 #if MC_VER < MC_1_21_3
Vec3 colorVec3 = this.level.getCloudColor(tickDelta); Vec3 colorVec3 = null;
return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z); try
{
colorVec3 = this.level.getCloudColor(tickDelta);
return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z);
}
catch (Exception e)
{
// extra logging is due to some mods returning weird values, this way we can track down the issue better
if (!this.cloudColorFailLogged)
{
this.cloudColorFailLogged = true;
String colorString = "NULL";
if (colorVec3 != null)
{
colorString = "r["+(float)colorVec3.x+"] g["+(float)colorVec3.y+"] b["+(float)colorVec3.z+"]";
}
LOGGER.warn("Failed to get cloud color for ["+this.getDhIdentifier()+"]. vec3 ["+colorString+"], error: ["+e.getMessage()+"].", e);
}
// default to white if there's an issue
return Color.WHITE;
}
#elif MC_VER <= MC_1_21_10 #elif MC_VER <= MC_1_21_10
int argbColor = this.level.getCloudColor(tickDelta); int argbColor = 0;
return ColorUtil.toColorObjARGB(argbColor); try
{
argbColor = this.level.getCloudColor(tickDelta);
return ColorUtil.toColorObjARGB(argbColor);
}
catch (Exception e)
{
// extra logging is due to some mods returning weird values, this way we can track down the issue better
if (!this.cloudColorFailLogged)
{
this.cloudColorFailLogged = true;
LOGGER.warn("Failed to get cloud color for ["+this.getDhIdentifier()+"]. Int ["+argbColor+"], col ["+ColorUtil.toString(argbColor)+"], error: ["+e.getMessage()+"].", e);
}
// default to white if there's an issue
return Color.WHITE;
}
#else #else
int argbColor = this.level.environmentAttributes().getValue(EnvironmentAttributes.CLOUD_COLOR, BlockPos.ZERO); int argbColor = 0;
return new Color(ColorUtil.getRed(argbColor), ColorUtil.getGreen(argbColor), ColorUtil.getBlue(argbColor), 255 /* ignore alpha since DH clouds don't render correctly with transparency */); try
{
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 */);
}
catch (Exception e)
{
// extra logging is due to some mods returning weird values, this way we can track down the issue better
if (!this.cloudColorFailLogged)
{
this.cloudColorFailLogged = true;
LOGGER.warn("Failed to get cloud color for ["+this.getDhIdentifier()+"]. Int ["+argbColor+"], col ["+ColorUtil.toString(argbColor)+"], error: ["+e.getMessage()+"].", e);
}
// default to white if there's an issue
return Color.WHITE;
}
#endif #endif
} }
@@ -187,7 +187,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
return this.level.dimension().location().toString(); return this.level.dimension().location().toString();
#else #else
return this.level.dimension().identifier().getPath(); return this.level.dimension().identifier().toString();
#endif #endif
} }
@@ -223,23 +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 @Override
public ServerLevel getWrappedMcObject() { return this.level; } public ServerLevel getWrappedMcObject() { return this.level; }
@@ -28,6 +28,7 @@ import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader; import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.*; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.*;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.level.IDhServerLevel; import com.seibel.distanthorizons.core.level.IDhServerLevel;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
@@ -37,6 +38,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.util.ExceptionUtil; import com.seibel.distanthorizons.core.util.ExceptionUtil;
import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.TimerUtil;
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 com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
@@ -100,6 +102,15 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS); public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
public static final int EXCEPTION_COUNTER_TRIGGER = 20; public static final int EXCEPTION_COUNTER_TRIGGER = 20;
/**
* 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;
private final IDhServerLevel dhServerLevel; private final IDhServerLevel dhServerLevel;
@@ -107,6 +118,8 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
public final InternalServerGenerator internalServerGenerator; public final InternalServerGenerator internalServerGenerator;
public final ChunkFileReader chunkFileReader; public final ChunkFileReader chunkFileReader;
private final Timer chunkSaveIgnoreTimer = TimerUtil.CreateTimer("ChunkSaveIgnoreTimer");
public final LinkedBlockingQueue<GenerationEvent> generationEventQueue = new LinkedBlockingQueue<>(); public final LinkedBlockingQueue<GenerationEvent> generationEventQueue = new LinkedBlockingQueue<>();
@@ -435,10 +448,9 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
//=============================// //=========================//
// process existing chunks // // process existing chunks //
// //=========================//
//=============================//
ArrayGridList<ChunkWrapper> chunkWrapperList = new ArrayGridList<>(regionChunks.gridSize); ArrayGridList<ChunkWrapper> chunkWrapperList = new ArrayGridList<>(regionChunks.gridSize);
regionChunks.forEachPos((relX, relZ) -> regionChunks.forEachPos((relX, relZ) ->
@@ -454,8 +466,8 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
} }
else if (chunk != null) else if (chunk != null)
{ {
//
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper()); ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper());
chunkWrapper.createDhHeightMaps();
chunkWrapperList.set(relX, relZ, chunkWrapper); chunkWrapperList.set(relX, relZ, chunkWrapper);
// try setting the wrapper's lighting // try setting the wrapper's lighting
@@ -575,6 +587,11 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
ProtoChunk protoChunk = ((ProtoChunk) chunk); ProtoChunk protoChunk = ((ProtoChunk) chunk);
protoChunk.setLightEngine(region.getLightEngine()); protoChunk.setLightEngine(region.getLightEngine());
} }
// usually ignoring the chunk's position is unnecessary,
// but this improves performance if a chunk update event does sneak through
SharedApi.CHUNK_UPDATE_QUEUE_MANAGER.addPosToIgnore(chunkWrapper.getChunkPos());
}); });
@@ -684,6 +701,24 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
this.dhServerLevel.updateBeaconBeamsForChunkPos(centerChunkWrapper.getChunkPos(), activeBeamList); this.dhServerLevel.updateBeaconBeamsForChunkPos(centerChunkWrapper.getChunkPos(), activeBeamList);
} }
} }
for (int i = 0; i < iChunkWrapperList.size(); i++)
{
ChunkWrapper chunkWrapper = (ChunkWrapper) iChunkWrapperList.get(i);
if (chunkWrapper == null)
{
continue;
}
// 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(chunkWrapper.getChunkPos()); }
}, MS_TO_IGNORE_CHUNK_AFTER_COMPLETION);
}
} }
} }
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); } private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); }
@@ -7,6 +7,7 @@ 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.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.level.IDhServerLevel; import com.seibel.distanthorizons.core.level.IDhServerLevel;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -51,7 +52,7 @@ public class InternalServerGenerator
/** /**
* Used to revert the ignore logic in {@link SharedApi} so * Used to revert the ignore logic in {@link SharedApi} so
* that given chunk pos can be handled again. * 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 * A timer is used so we don't have to inject into MC's code and it works sell enough
* most of the time. * 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. * If a chunk does get through due the timeout not being long enough that isn't the end of the world.
@@ -156,6 +157,7 @@ public class InternalServerGenerator
if (chunk != null) if (chunk != null)
{ {
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper()); ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper());
chunkWrapper.createDhHeightMaps();
chunkWrappers.add(chunkWrapper); chunkWrappers.add(chunkWrapper);
} }
} }
@@ -217,8 +219,7 @@ public class InternalServerGenerator
if (Config.Common.Logging.Warning.showSlowWorldGenSettingWarnings.get()) if (Config.Common.Logging.Warning.showSlowWorldGenSettingWarnings.get())
{ {
String message = String message =
// orange text MinecraftTextFormat.ORANGE + "Distant Horizons: slow world gen." + MinecraftTextFormat.CLEAR_FORMATTING + "\n" +
"\u00A76" + "Distant Horizons: slow world gen." + "\u00A7r\n" +
c2meWarning; c2meWarning;
ClientApi.INSTANCE.showChatMessageNextFrame(message); ClientApi.INSTANCE.showChatMessageNextFrame(message);
} }
@@ -222,7 +222,8 @@ public class ChunkCompoundTagParser
boolean hasHeightmapData = readHeightmaps(chunk, chunkData); boolean hasHeightmapData = readHeightmaps(chunk, chunkData);
// chunk wrapper so we can pass along extra data more easily // chunk wrapper so we can pass along extra data more easily
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, dhServerLevel.getServerLevelWrapper(), !hasHeightmapData); ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, dhServerLevel.getServerLevelWrapper());
chunkWrapper.createDhHeightMaps();
@@ -293,7 +293,7 @@ public class ChunkFileReader implements AutoCloseable
public ChunkWrapper CreateProtoChunkWrapper(ServerLevel level, ChunkPos chunkPos) public ChunkWrapper CreateProtoChunkWrapper(ServerLevel level, ChunkPos chunkPos)
{ {
ProtoChunk chunk = CreateProtoChunk(level, chunkPos); ProtoChunk chunk = CreateProtoChunk(level, chunkPos);
return new ChunkWrapper(chunk, this.params.dhServerLevel.getLevelWrapper(), false); return new ChunkWrapper(chunk, this.params.dhServerLevel.getLevelWrapper());
} }
public static ProtoChunk CreateProtoChunk(ServerLevel level, ChunkPos chunkPos) public static ProtoChunk CreateProtoChunk(ServerLevel level, ChunkPos chunkPos)
{ {
@@ -24,6 +24,9 @@ accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager; 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; 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 # 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/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/IOWorker storage Lnet/minecraft/world/level/chunk/storage/RegionFileStorage;
@@ -22,8 +22,10 @@ package com.seibel.distanthorizons.fabric;
import com.seibel.distanthorizons.common.AbstractModInitializer; import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender; import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
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.logging.DhLogger;
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.api.internal.SharedApi;
@@ -64,11 +66,13 @@ import java.util.concurrent.AbstractExecutorService;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
#endif #endif
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.multiplayer.ClientLevel; 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 com.seibel.distanthorizons.core.logging.DhLogger;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
/** /**
@@ -82,13 +86,12 @@ import org.lwjgl.glfw.GLFW;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public class FabricClientProxy implements AbstractModInitializer.IEventProxy public class FabricClientProxy implements AbstractModInitializer.IEventProxy
{ {
private final ClientApi clientApi = ClientApi.INSTANCE;
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 DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
// TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi private static final MinecraftClientWrapper MC = MinecraftClientWrapper.INSTANCE;
private static final int[] KEY_TO_CHECK_FOR = { GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8, GLFW.GLFW_KEY_P}; private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static final ClientApi clientApi = ClientApi.INSTANCE;
HashSet<Integer> previouslyPressKeyCodes = new HashSet<>(); HashSet<Integer> previouslyPressKeyCodes = new HashSet<>();
@@ -113,14 +116,6 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
//=============//
// tick events //
//=============//
ClientTickEvents.START_CLIENT_TICK.register((client) -> { ClientApi.INSTANCE.clientTickEvent(); });
//==============// //==============//
// chunk events // // chunk events //
//==============// //==============//
@@ -344,23 +339,13 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
{ {
HashSet<Integer> currentKeyDown = new HashSet<>(); HashSet<Integer> currentKeyDown = new HashSet<>();
// Note: Minecraft's InputConstants is same as GLFW Key values // Note: Minecraft's InputConstants are the same as GLFW Key values
//TODO: Use mixin to hook directly into the GLFW Keyboard event in minecraft KeyboardHandler for (int keyCode = GLFW.GLFW_KEY_0; keyCode <= GLFW.GLFW_KEY_LAST; keyCode++)
// Check all keys we need
for (int keyCode = GLFW.GLFW_KEY_A; keyCode <= GLFW.GLFW_KEY_Z; keyCode++)
{ {
//if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode)) if (InputConstants.isKeyDown(MC.getGlfwWindowId(), keyCode))
//{ {
// currentKeyDown.add(keyCode); currentKeyDown.add(keyCode);
//} }
}
for (int keyCode : KEY_TO_CHECK_FOR)
{
//if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keyCode))
//{
// currentKeyDown.add(keyCode);
//}
} }
// Diff and trigger events // Diff and trigger events
@@ -25,6 +25,7 @@ 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.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,7 +39,6 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import com.seibel.distanthorizons.core.logging.DhLogger; 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;
@@ -103,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.";
@@ -137,24 +137,24 @@ public class MixinOptionsScreen extends Screen
if (this.optionsButton == null) if (this.optionsButton == null)
{ {
this.optionsButton this.optionsButton
= new TexturedButtonWidget( = new TexturedButtonWidget(
// Where the button is on the screen // Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12, this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button // Width and height of the button
20, 20, 20, 20,
// texture UV Offset // texture UV Offset
0, 0, 0, 0,
// Some textuary stuff // Some textuary stuff
20, ICON_TEXTURE, 20, 40, 20, ICON_TEXTURE, 20, 40,
// Create the button and tell it where to go // Create the button and tell it where to go
// For now it goes to the client option by default // For now it goes to the client option by default
(buttonWidget) -> Objects.requireNonNull(this.minecraft).setScreen(GetConfigScreen.getScreen(this)), (buttonWidget) -> Objects.requireNonNull(this.minecraft).setScreen(GetConfigScreen.getScreen(this)),
// Add a title to the button // Add a title to the button
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
new TranslatableComponent(ModInfo.ID + ".title")); new TranslatableComponent(ModInfo.ID + ".title"));
#else #else
Component.translatable(ModInfo.ID + ".title")); Component.translatable(ModInfo.ID + ".title"));
#endif #endif
} }
return this.optionsButton; return this.optionsButton;
@@ -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;
@@ -104,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,
@@ -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);
@@ -57,25 +57,27 @@ public class MixinOptionsScreen extends Screen
private void lodconfig$init(CallbackInfo ci) private void lodconfig$init(CallbackInfo ci)
{ {
if (Config.Client.showDhOptionsButtonInMinecraftUi.get()) if (Config.Client.showDhOptionsButtonInMinecraftUi.get())
{
this. #if MC_VER < MC_1_17_1 addButton #else addRenderableWidget #endif this. #if MC_VER < MC_1_17_1 addButton #else addRenderableWidget #endif
(new TexturedButtonWidget( (new TexturedButtonWidget(
// Where the button is on the screen // Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12, this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button // Width and height of the button
20, 20, 20, 20,
// Offset // Offset
0, 0, 0, 0,
// Some textuary stuff // Some textuary stuff
20, ICON_TEXTURE, 20, 40, 20, ICON_TEXTURE, 20, 40,
// Create the button and tell it where to go // Create the button and tell it where to go
// For now it goes to the client option by default // For now it goes to the client option by default
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)), (buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
// Add a title to the button // Add a title to the button
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
new TranslatableComponent(ModInfo.ID + ".title"))); new TranslatableComponent(ModInfo.ID + ".title")));
#else #else
Component.translatable(ModInfo.ID + ".title"))); Component.translatable(ModInfo.ID + ".title")));
#endif #endif
}
} }
} }
@@ -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;
}
}
+3 -4
View File
@@ -12,14 +12,13 @@ issueTrackerURL = "${issues}"
#//updateJSONURL="https://change.me.example.invalid/updates.json" # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ #//updateJSONURL="https://change.me.example.invalid/updates.json" # A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
displayURL = "${homepage}" displayURL = "${homepage}"
description = "${description}" #//mandatory. The description text for the mod description = "${description}" #//mandatory. The description text for the mod
logoFile = "assets/distanthorizons/logo.png" logoFile = "dh_forge_logo.png" #// can't contain a file path due to an old forge limitation https://github.com/MinecraftForge/MinecraftForge/issues/7348
catalogueImageIcon = "assets/distanthorizons/icon.png" catalogueImageIcon = "dh_forge_icon.png" #// can't contain a file path due to an old forge limitation https://github.com/MinecraftForge/MinecraftForge/issues/7348
credits = "Massive thanks to all the developers for their hard work to bring Distant Horizons to where it is today. - James" credits = "Massive thanks to all the developers for their hard work to bring Distant Horizons to where it is today. - James"
#// if not set defaults to "false" #// if not set defaults to "false"
clientSideOnly = "true" clientSideOnly = "true"
#// if not set side defaults to "BOTH" #// if not set side defaults to "BOTH"
#// TODO change to "BOTH" when we add server support side = "BOTH"
side = "CLIENT"
#// Allow any version to be present (or not) on the server #// Allow any version to be present (or not) on the server
acceptableRemoteVersions = "*" acceptableRemoteVersions = "*"
+3 -3
View File
@@ -5,8 +5,8 @@ org.gradle.caching=true
# Mod Info # Mod Info
mod_name=DistantHorizons mod_name=DistantHorizons
mod_version=2.4.0-b mod_version=2.4.6-b-dev
api_version=5.0.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,7 +18,7 @@ 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
@@ -73,29 +73,6 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
//=============//
// tick events //
//=============//
#if MC_VER < MC_1_20_6
@SubscribeEvent
public void clientTickEvent(TickEvent.ClientTickEvent event)
{
if (event.phase == TickEvent.Phase.START)
{
ClientApi.INSTANCE.clientTickEvent();
}
}
#else
@SubscribeEvent
public void clientTickEvent(ClientTickEvent.Pre event)
{
ClientApi.INSTANCE.clientTickEvent();
}
#endif
//==============// //==============//
// world events // // world events //
//==============// //==============//
@@ -33,9 +33,9 @@ public class IrisAccessor implements IIrisAccessor
{ {
public IrisAccessor() public IrisAccessor()
{ {
#if MC_VER == MC_1_21_11 //#if MC_VER == MC_1_21_11
throw new UnsupportedOperationException("Iris isn't supported on this version of DH. When this version of DH was created Iris wasn't available for Neoforge yet."); //throw new UnsupportedOperationException("Iris isn't supported on this version of DH. When this version of DH was created Iris wasn't available for Neoforge yet.");
#endif //#endif
} }
+14
View File
@@ -12,15 +12,29 @@ How to add a library's natives:
Example: Example:
```groovy ```groovy
// Relocate the namespace (Java side)
relocate "org.sqlite", "dh_sqlite", { relocate "org.sqlite", "dh_sqlite", {
// (Specific to SQLite's relocation)
// Make sure that native paths are not changed before steps below
exclude "org/sqlite/native/**" exclude "org/sqlite/native/**"
} }
// Shadow also replaces strings inside the Java code
// See the library's source code to find strings used to call into the native code
// This also includes native library paths, if you use mapPaths {} below they will likely need adjustment as well
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
transform(NativeTransformer) { transform(NativeTransformer) {
// NativeTransformer configuration // NativeTransformer configuration
rootDir = project.rootDir rootDir = project.rootDir
// Match native libraries
matchFiles { it.startsWith("org/sqlite") }
// Replace paths with ones that won't overlap with other mods
// Libraries are the ones choosing the path to use for natives; check the source code to see which paths are acceptable.
mapPaths { it.replace("org/sqlite", "dh_sqlite") }
// Replace native strings, e.g. used in calls back to Java // Replace native strings, e.g. used in calls back to Java
// They must be of the same length or shorter!
relocateNative "org/sqlite", "dh_sqlite" relocateNative "org/sqlite", "dh_sqlite"
// Rename native methods used when calling from Java // Rename native methods used when calling from Java
relocateNative "org_sqlite", "dh_1sqlite" relocateNative "org_sqlite", "dh_1sqlite"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -10,8 +10,8 @@ builds_for=fabric,forge
netty_version=4.1.82.Final netty_version=4.1.82.Final
# Fabric loader # Fabric loader
fabric_loader_version=0.15.6 fabric_loader_version=0.16.10
fabric_api_version=0.90.4+1.20.1 fabric_api_version=0.92.6+1.20.1
# Fabric mod versions # Fabric mod versions
modmenu_version=7.2.2 modmenu_version=7.2.2
starlight_version_fabric= starlight_version_fabric=