1.12.2 working in dev

This commit is contained in:
Vojtěch Šokala
2026-03-11 09:20:32 +01:00
parent 1d0d67d215
commit c5adc3f72a
128 changed files with 5096 additions and 502 deletions
+55 -15
View File
@@ -3,8 +3,8 @@ plugins {
id 'java-library'
id 'maven-publish'
id 'com.gradleup.shadow' version '9.2.2'
id 'xyz.wagyourtail.unimined' version '1.4.9-kappa'
id 'net.kyori.blossom' version '2.1.0'
id 'xyz.wagyourtail.unimined' version '1.4.10-kappa'
id 'net.kyori.blossom' version '2.1.0'
}
apply from: 'gradle/scripts/helpers.gradle'
@@ -56,7 +56,11 @@ unimined.minecraft {
}
cleanroom {
loader "0.3.31-alpha"
//propertyBool('use_access_transformer')
if (true) {
accessTransformer "${rootProject.projectDir}/cleanroom/src/main/resources/1_12_2_distanthorizons_at.cfg"
}
loader "0.4.4-alpha"
runs.auth.username = "Developer"
runs.all {
systemProperty("crl.dev.mixin", "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json")
@@ -64,15 +68,47 @@ unimined.minecraft {
if (extraArgs != null && !extraArgs.trim().isEmpty()) {
jvmArgs += extraArgs.split { "\\s+" }.toList()
}
if (propertyBool('enable_foundation_debug')) {
println "Classpath size BEFORE: ${classpath.files.size()}"
classpath = classpath.filter { file ->
def remove =
file.path.contains("DistantHorizons-common") ||
file.path.contains("DistantHorizons-core") ||
file.path.contains("DistantHorizons-api")
if (remove) {
println "Removing from classpath: $file"
}
return !remove
}
println "Classpath size AFTER: ${classpath.files.size()}"
def extraPath = [
sourceSets.main.output.classesDirs.asPath,
sourceSets.main.output.resourcesDir.absolutePath,
rootProject.project(':common').sourceSets.main.output.classesDirs.asPath,
rootProject.project(':core').sourceSets.main.output.classesDirs.asPath,
rootProject.project(':api').sourceSets.main.output.classesDirs.asPath,
].join(File.pathSeparator)
jvmArgs -= ("-Dcrl.dev.extrapath=")
jvmArgs += ("-Dcrl.dev.extrapath=${extraPath}")
if (false) {
systemProperty("foundation.dump", "true")
systemProperty("foundation.verbose", "true")
}
//propertyBool('is_coremod')
if (true) {
//coremod_plugin_class_name
systemProperty("fml.coreMods.load", propertyString('com.seibel.distanthorizons.forge.DistantHorizonsLoadingPlugin'))
//forge for now bcs it will crash but correct is .cleanroom
systemProperty("fml.coreMods.load", "com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin")
}
return
}
}
@@ -104,11 +140,7 @@ unimined.minecraft {
}
dependencies {
//propertyBool('enable_junit_testing')
if (true) {
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.1'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
compileOnly "com.cleanroommc:sponge-mixin:0.20.12+mixin.0.8.7"
}
processResources {
@@ -167,6 +199,13 @@ jar {
}
}
doFirst {
archiveClassifier = 'dev'
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
if (configurations.contain.size() > 0) {
into('/') {
from configurations.contain
}
}
manifest {
def attribute_map = [:]
attribute_map['ModType'] = "CRL"
@@ -178,14 +217,15 @@ jar {
//propertyBool('is_coremod')
if (true) {
//coremod_plugin_class_name
attribute_map['FMLCorePlugin'] = propertyString('com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin')
attribute_map['FMLCorePlugin'] = "com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin"
//coremod_includes_mod
if (true) {
attribute_map['FMLCorePluginContainsFMLMod'] = true
}
}
if (propertyBool('use_access_transformer')) {
attribute_map['FMLAT'] = propertyString('access_transformer_locations')
//propertyBool('use_access_transformer')
if (true) {
attribute_map['FMLAT'] = "1_12_2_distanthorizons_at.cfg"
}
attributes(attribute_map)
}
@@ -197,7 +237,6 @@ jar {
}
}
shadowJar {
configurations = [project.configurations.shadow]
archiveClassifier = "shadow"
@@ -221,7 +260,8 @@ test {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(21)
})
if (propertyBool('show_testing_output')) {
//propertyBool('show_testing_output')
if (false) {
testLogging {
showStandardStreams = true
}
@@ -0,0 +1,245 @@
/*
* 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.cleanroom;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL32;
import java.util.concurrent.AbstractExecutorService;
/**
* This handles all events sent to the client,
* and is the starting point for most of the mod.
*
* @author James_Seibel
* @version 2023-7-27
*/
public class CleanroomClientProxy implements AbstractModInitializer.IEventProxy
{
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static World GetEventLevel(WorldEvent e) { return e.getWorld(); }
@Override
public void registerEvents()
{
MinecraftForge.EVENT_BUS.register(this);
// handles singleplayer, LAN, and connecting to a server
PACKET_SENDER.setPacketHandler((IServerPlayerWrapper player, @NotNull AbstractNetworkMessage message) ->
{
ClientApi.INSTANCE.pluginMessageReceived(message);
ServerApi.INSTANCE.pluginMessageReceived(player, message);
});
}
//==============//
// world events //
//==============//
@SubscribeEvent
public void clientLevelLoadEvent(WorldEvent.Load event)
{
LOGGER.info("level load");
World level = event.getWorld();
if (!(level instanceof WorldClient clientLevel))
{
return;
}
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel, true);
ClientApi.INSTANCE.clientLevelLoadEvent(clientLevelWrapper);
}
@SubscribeEvent
public void clientLevelUnloadEvent(WorldEvent.Unload event)
{
LOGGER.info("level unload");
World level = event.getWorld();
if (!(level instanceof WorldClient clientLevel))
{
return;
}
IClientLevelWrapper clientLevelWrapper = ClientLevelWrapper.getWrapper(clientLevel);
ClientApi.INSTANCE.clientLevelUnloadEvent(clientLevelWrapper);
}
//==============//
// chunk events //
//==============//
@SubscribeEvent
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
{
if (MC.clientConnectedToDedicatedServer())
{
World level = event.getWorld();
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ()))
{
return;
}
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
Chunk chunk = level.getChunk(event.getPos());
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
});
}
}
}
@SubscribeEvent
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
{
if (MC.clientConnectedToDedicatedServer())
{
World level = event.getWorld();
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ()))
{
return;
}
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
Chunk chunk = level.getChunk(event.getPos());
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
});
}
}
}
@SubscribeEvent
public void clientChunkLoadEvent(ChunkEvent.Load event)
{
if (MC.clientConnectedToDedicatedServer())
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunkWrapper = new ChunkWrapper(event.getChunk(), wrappedLevel);
SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, wrappedLevel);
}
}
//==============//
// key bindings //
//==============//
@SubscribeEvent
public void registerKeyBindings(InputEvent.KeyInputEvent event)
{
/* if (Minecraft.getMinecraft().player == null)
{
return;
}
if (event.getAction() != GLFW.GLFW_PRESS)
{
return;
}
ClientApi.INSTANCE.keyPressedEvent(event.getKey());*/
}
//===========//
// rendering //
//===========//
@SubscribeEvent
public void afterLevelRenderEvent(TickEvent.RenderTickEvent event)
{
if (event.type.equals(TickEvent.RenderTickEvent.Type.RENDER))
{
try
{
// should generally only need to be set once per game session
// allows DH to render directly to Optifine's level frame buffer,
// allowing better shader support
MinecraftRenderWrapper.INSTANCE.finalLevelFrameBufferId = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
}
catch (Exception | Error e)
{
LOGGER.error("Unexpected error in afterLevelRenderEvent: "+e.getMessage(), e);
}
}
}
@SubscribeEvent
public void onRenderOverlay(RenderGameOverlayEvent.Text event) {
Minecraft mc = Minecraft.getMinecraft();
if (event.isCanceled() || !mc.gameSettings.showDebugInfo) return;
F3Screen.addStringToDisplay(event.getRight());
}
}
@@ -0,0 +1,129 @@
/*
* 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.cleanroom;
import com.seibel.distanthorizons.cleanroom.modAccessor.ModChecker;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import java.util.function.Consumer;
/**
* Initialize and setup the Mod. <br>
* If you are looking for the real start of the mod
* check out the ClientProxy.
*/
@Mod(modid = ModInfo.ID, name = ModInfo.NAME, version = ModInfo.VERSION)
public class CleanroomMain extends AbstractModInitializer
{
@Mod.Instance
public static CleanroomMain instance;
@Mod.EventHandler
public void init(FMLInitializationEvent event)
{
if (FMLCommonHandler.instance().getEffectiveSide().isClient())
{
this.onInitializeClient();
}
else
{
this.onInitializeServer();
}
}
@Override
protected void createInitialSharedBindings()
{
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new CleanroomPluginPacketSender());
}
@Override
protected void createInitialClientBindings() { /* no additional setup needed currently */ }
@Override
protected IEventProxy createClientProxy() { return new CleanroomClientProxy(); }
@Override
protected IEventProxy createServerProxy(boolean isDedicated) { return new CleanroomServerProxy(isDedicated); }
@Override
protected void initializeModCompat()
{
}
/* @Override
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
{ MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); }); }*/
@Override
protected void subscribeClientStartedEvent(Runnable eventHandler)
{
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
// to signify readiness other than FmlClientSetupEvent
eventHandler.run();
}
@Mod.EventHandler
public void onServerAboutToStart(FMLServerAboutToStartEvent event)
{
if (eventHandlerStartServer != null)
{
eventHandlerStartServer.accept(event.getServer());
}
}
Consumer<MinecraftServer> eventHandlerStartServer;
@Override
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
{
eventHandlerStartServer = eventHandler;
}
@Override
protected void runDelayedSetup() { SingletonInjector.INSTANCE.runDelayedSetup(); }
// ServerWorldLoadEvent
@Mod.EventHandler
public void dedicatedWorldLoadEvent(FMLServerAboutToStartEvent event)
{
ServerApi.INSTANCE.serverLoadEvent(event.getServer().isDedicatedServer());
}
// ServerWorldUnloadEvent
@Mod.EventHandler
public void serverWorldUnloadEvent(FMLServerStoppingEvent event)
{
ServerApi.INSTANCE.serverUnloadEvent();
}
}
@@ -0,0 +1,96 @@
package com.seibel.distanthorizons.cleanroom;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class CleanroomPluginPacketSender extends AbstractPluginPacketSender
{
public static final SimpleNetworkWrapper PLUGIN_CHANNEL =
NetworkRegistry.INSTANCE.newSimpleChannel(
AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE
);
public static void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
{
setPacketHandler((player, message) -> consumer.accept(message));
}
static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumerPacket;
public static void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
{
PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.CLIENT);
PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.SERVER);
consumerPacket = consumer;
}
@Override
public void sendToServer(AbstractNetworkMessage message)
{
PLUGIN_CHANNEL.sendToServer(new MessageWrapper(message));
}
@Override
public void sendToClient(EntityPlayerMP serverPlayer, AbstractNetworkMessage message)
{
PLUGIN_CHANNEL.sendTo(new MessageWrapper(message), serverPlayer);
}
// Forge doesn't support using abstract classes
@SuppressWarnings({"ClassCanBeRecord", "RedundantSuppression"})
public static class MessageWrapper implements IMessage
{
public AbstractNetworkMessage message;
public MessageWrapper(AbstractNetworkMessage message) { this.message = message; }
public MessageWrapper()
{
// For reflection
}
@Override
public void fromBytes(ByteBuf buf) {
int messageId = buf.readByte();
message = MessageRegistry.INSTANCE.createMessage(messageId);
message.decode(buf);
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeByte(MessageRegistry.INSTANCE.getMessageId(message));
message.encode(buf);
}
public static class Handler implements IMessageHandler<MessageWrapper, IMessage>
{
@Override
public IMessage onMessage(MessageWrapper wrapper, MessageContext context) {
if (wrapper.message != null)
{
if (context.side == Side.SERVER)
{
consumerPacket.accept(ServerPlayerWrapper.getWrapper(context.getServerHandler().player), wrapper.message);
}
else {
consumerPacket.accept(null, wrapper.message);
}
}
return null; // No response needed
}
}
}
}
@@ -0,0 +1,149 @@
package com.seibel.distanthorizons.cleanroom;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import java.lang.reflect.Field;
public class CleanroomServerProxy implements AbstractModInitializer.IEventProxy
{
private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static World GetEventLevel(WorldEvent e) { return e.getWorld(); }
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private final ServerApi serverApi = ServerApi.INSTANCE;
private final boolean isDedicated;
@Override
public void registerEvents()
{
MinecraftForge.EVENT_BUS.register(this);
if (this.isDedicated)
{
PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
}
}
//=============//
// constructor //
//=============//
public CleanroomServerProxy(boolean isDedicated) { this.isDedicated = isDedicated; }
//========//
// events //
//========//
// ServerLevelLoadEvent
@SubscribeEvent
public void serverLevelLoadEvent(WorldEvent.Load event)
{
if (GetEventLevel(event) instanceof WorldServer)
{
this.serverApi.serverLevelLoadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event)));
InternalServerGenerator.DH_SERVER_GEN_TICKET = ForgeChunkManager.requestTicket(CleanroomMain.instance, event.getWorld(), ForgeChunkManager.Type.NORMAL);
//increase chunk limit
try
{
Field maxDepthField = InternalServerGenerator.DH_SERVER_GEN_TICKET.getClass().getDeclaredField("maxDepth");
maxDepthField.setAccessible(true);
maxDepthField.setInt(InternalServerGenerator.DH_SERVER_GEN_TICKET, 1000);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
// ServerLevelUnloadEvent
@SubscribeEvent
public void serverLevelUnloadEvent(WorldEvent.Unload event)
{
if (GetEventLevel(event) instanceof WorldServer)
{
this.serverApi.serverLevelUnloadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event)));
}
}
@SubscribeEvent
public void serverChunkLoadEvent(ChunkEvent.Load event)
{
ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), levelWrapper);
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
}
@SubscribeEvent
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
{ this.serverApi.serverPlayerJoinEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event)
{ this.serverApi.serverPlayerDisconnectEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event)
{
this.serverApi.serverPlayerLevelChangeEvent(
getServerPlayerWrapper(event),
getServerLevelWrapper(event.fromDim, event),
getServerLevelWrapper(event.toDim, event)
);
}
//================//
// helper methods //
//================//
private static ServerLevelWrapper getServerLevelWrapper(WorldServer level) { return ServerLevelWrapper.getWrapper(level); }
private static ServerLevelWrapper getServerLevelWrapper(int dimensionId, PlayerEvent event)
{
MinecraftServer server = event.player.getServer();
if (server == null)
{
LOGGER.error("getServerLevelWrapper: server is null for player {}", event.player.getName());
return null;
}
return getServerLevelWrapper(server.getWorld(dimensionId));
}
private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event)
{
return ServerPlayerWrapper.getWrapper((EntityPlayerMP) event.player);
}
}
@@ -0,0 +1,37 @@
package com.seibel.distanthorizons.cleanroom;
import net.minecraftforge.fml.common.Loader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Set;
public class DistantHorizonsConfigPlugin implements IMixinConfigPlugin
{
private static final Logger LOGGER = LogManager.getLogger();
@Override
public void onLoad(String mixinPackage)
{ }
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
{
/* return switch (mixinClassName.split("\\.")[5]) {
case "mist" -> Loader.isModLoaded("mist");
default -> true;
};*/
return true;
}
@Override public String getRefMapperConfig() { return null; }
@Override public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { }
@Override public List<String> getMixins() { return null; }
@Override public void preApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { }
@Override public void postApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { }
}
@@ -0,0 +1,33 @@
package com.seibel.distanthorizons.cleanroom;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class DistantHorizonsLoadingPlugin implements IFMLLoadingPlugin
{
@Override
public @Nullable String[] getASMTransformerClass()
{
return new String[0];
}
@Override
public @Nullable String getModContainerClass()
{
return null;
}
@Override
public @Nullable String getSetupClass()
{
return null;
}
@Override
public void injectData(Map<String, Object> data) { }
@Override
public @Nullable String getAccessTransformerClass()
{
return null;
}
}
@@ -0,0 +1,71 @@
package com.seibel.distanthorizons.cleanroom.mixins.client;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.init.MobEffects;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(EntityRenderer.class)
public class MixinEntityRenderer
{
@Shadow
@Final
private DynamicTexture lightmapTexture;
@Shadow @Final private Minecraft mc;
@Shadow @Final private static Logger LOGGER;
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("TAIL"), method = "updateLightmap")
public void onUpdateLightmap(float patrialTicks, CallbackInfo ci)
{
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
if (mc == null || mc.getWrappedClientLevel() == null)
{
return;
}
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
renderWrapper.setLightmapId(lightmapTexture.getGlTextureId(), clientLevel);
}
@Inject(at = @At("RETURN"), method = "setupFog")
private void disableSetupFog(int startCoords, float partialTicks, CallbackInfo ci)
{
boolean cameraNotInFluid = mc.getRenderViewEntity() != null && !mc.world.getBlockState(mc.getRenderViewEntity().getPosition()).getMaterial().isLiquid();
boolean isSpecialFog = mc.player.isPotionActive(MobEffects.BLINDNESS);
if (!isSpecialFog
&& cameraNotInFluid
&& startCoords == 0 // 0 = terrain fog
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
{
GlStateManager.setFogStart(A_REALLY_REALLY_BIG_VALUE);
GlStateManager.setFogEnd(A_EVEN_LARGER_VALUE);
ClientApi.RENDER_STATE.vanillaFogEnabled = false;
}
else
{
ClientApi.RENDER_STATE.vanillaFogEnabled = true;
}
}
}
@@ -0,0 +1,27 @@
package com.seibel.distanthorizons.cleanroom.mixins.client;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.SPacketJoinGame;
import net.minecraft.util.text.ITextComponent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(NetHandlerPlayClient.class)
public class MixinNetHandlerPlayClient
{
@Inject(method = "handleJoinGame", at = @At("RETURN"))
private void onHandleJoinGameEnd(SPacketJoinGame packet, CallbackInfo ci)
{
ClientApi.INSTANCE.onClientOnlyConnected();
}
@Inject(method = "onDisconnect", at = @At("RETURN"))
private void onDisconnect(ITextComponent reason, CallbackInfo ci)
{
ClientApi.INSTANCE.onClientOnlyDisconnected();
}
}
@@ -0,0 +1,83 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.cleanroom.mixins.client;
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiOptions;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Adds a button to the menu to goto the config
*
* @author coolGi
* @version 12-02-2021
*/
@Mixin(GuiOptions.class)
public class MixinOptionsScreen extends GuiScreen
{
// Get the texture for the button
@Unique private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
@Unique private static final int button_id = 99;
@Inject(at = @At("HEAD"), method = "initGui")
private void lodconfig$init(CallbackInfo ci)
{
if (Config.Client.showDhOptionsButtonInMinecraftUi.get())
this.buttonList.add(
(new TexturedButtonWidget(
button_id,
// Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button
20, 20,
// Offset
0, 0,
// Some textuary stuff
20, ICON_TEXTURE, 20, 40,
// Create the button and tell it where to go
// For now it goes to the client option by default
// Add a title to the button
"DH" /* ModInfo.ID + ".title" */)));
}
@Inject(at = @At("HEAD"), method = "actionPerformed", cancellable = true)
private void lodconfig$actionPerformed(GuiButton button, CallbackInfo ci)
{
if (button.id == button_id)
{
Minecraft.getMinecraft().displayGuiScreen(GetConfigScreen.getScreen(this));
ci.cancel();
}
}
}
@@ -0,0 +1,62 @@
package com.seibel.distanthorizons.cleanroom.mixins.client;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.Entity;
import net.minecraft.util.BlockRenderLayer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RenderGlobal.class)
public class MixinRenderGlobal
{
@Shadow private WorldClient world;
@Inject(method = "renderBlockLayer(Lnet/minecraft/util/BlockRenderLayer;DILnet/minecraft/entity/Entity;)I", at = @At("HEAD"))
private void renderChunkLayer(BlockRenderLayer blockLayerIn, double partialTicks, int pass, Entity entityIn, CallbackInfoReturnable<Integer> cir)
{
if (blockLayerIn == BlockRenderLayer.SOLID)
{
float[] mcProjMatrixRaw = new float[16];
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
ClientApi.RENDER_STATE.mcProjectionMatrix.transpose();
float[] mcModelViewRaw = new float[16];
GL11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, mcModelViewRaw);
ClientApi.RENDER_STATE.mcModelViewMatrix = new Mat4f(mcModelViewRaw);
ClientApi.RENDER_STATE.mcModelViewMatrix.transpose();
ClientApi.RENDER_STATE.partialTickTime = (float) partialTicks;
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.world);
int blendSrc = GL11.glGetInteger(GL11.GL_BLEND_SRC);
int blendDst = GL11.glGetInteger(GL11.GL_BLEND_DST);
int boundTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
ClientApi.INSTANCE.renderLods();
GL30.glBindVertexArray(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glUseProgram(0);
//Restore vanilla states
GlStateManager.depthFunc(GL11.GL_LEQUAL);
GlStateManager.bindTexture(boundTexture);
GlStateManager.tryBlendFuncSeparate(blendSrc, blendDst, GL11.GL_ONE, GL11.GL_ZERO);
}
}
}
@@ -0,0 +1,26 @@
package com.seibel.distanthorizons.cleanroom.mixins.common;
import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ChunkProviderServer.class)
public class MixinChunkProviderServer
{
@Shadow
@Final
public WorldServer world;
@Inject(method = "saveChunkData", at = @At("RETURN"))
private void onSaveChunkData(Chunk chunk, CallbackInfo ci)
{
MixinChunkMapCommon.onChunkSave(world, chunk);
}
}
@@ -0,0 +1,49 @@
package com.seibel.distanthorizons.cleanroom.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.ITeleporter;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(EntityPlayerMP.class)
public abstract class MixinEntityPlayerMP implements IMixinServerPlayer
{
@Shadow
@Final
public MinecraftServer server;
@Unique
@Nullable
private volatile WorldServer distantHorizons$dimensionChangeDestination;
@Override
@Nullable
public WorldServer distantHorizons$getDimensionChangeDestination()
{
return this.distantHorizons$dimensionChangeDestination;
}
@Inject(at = @At("HEAD"), method = "changeDimension(ILnet/minecraftforge/common/util/ITeleporter;)Lnet/minecraft/entity/Entity;")
public void setDimensionChangeDestination(int destinationDimensionID, ITeleporter teleporter, CallbackInfoReturnable<Entity> cir)
{
this.distantHorizons$dimensionChangeDestination = this.server.getWorld(destinationDimensionID);
}
@Inject(at = @At("RETURN"), method = "clearInvulnerableDimensionChange")
public void clearDimensionChangeDestination(CallbackInfo ci)
{
this.distantHorizons$dimensionChangeDestination = null;
}
}
@@ -0,0 +1,52 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.cleanroom.modAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import java.io.File;
import java.util.Optional;
import java.util.stream.Stream;
public class ModChecker implements IModChecker
{
public static final ModChecker INSTANCE = new ModChecker();
@Override
public boolean isModLoaded(String modid)
{
return Loader.isModLoaded(modid);
}
@Override
public File modLocation(String modid)
{
Stream<ModContainer> foundStream = Loader.instance().getModList().stream().filter(x -> x.getModId().equals(modid));
Optional<ModContainer> container = foundStream.findFirst();
if (!container.isPresent())
{
throw new RuntimeException("Mod not found: " + modid);
}
return container.get().getSource();
}
}
@@ -0,0 +1,3 @@
public net.minecraft.client.renderer.EntityRenderer getFOVModifier(FZ)F
public net.minecraft.client.renderer.ActiveRenderInfo MODELVIEW
public net.minecraft.client.renderer.ActiveRenderInfo PROJECTION
@@ -0,0 +1,647 @@
#PARSE_ESCAPES
distanthorizons.title=Distant Horizons
distanthorizons.general.true=True
distanthorizons.general.false=False
distanthorizons.general.yes=Yes
distanthorizons.general.no=No
distanthorizons.general.back=Back
distanthorizons.general.next=Next
distanthorizons.general.done=Done
distanthorizons.general.cancel=Cancel
distanthorizons.general.reset=Reset
distanthorizons.general.spacer=
distanthorizons.general.apiOverride=API LOCK
distanthorizons.general.disabledByApi.@tooltip=This option is controlled by another mod via DH's API \nso it cannot be changed via the UI or config file.
distanthorizons.updater.title=Distant Horizons auto updater
distanthorizons.updater.text1=§lNew update available!
distanthorizons.updater.text2=§fDo you want to update from %s§f to %s§f?
distanthorizons.updater.later=Not now
distanthorizons.updater.never=Don't show again
distanthorizons.updater.update=Update
distanthorizons.updater.update.@tooltip=Updates the mod this one time\n(Updates when game is closed)
distanthorizons.updater.silent=Always silent update
distanthorizons.updater.silent.@tooltip=Every time an update is available, it would update\n(§6WARNING§r: This wont prompt you when updating)
distanthorizons.updater.waitingForClose=Distant Horizons will finish updating once the game restarts
distanthorizons.config.title=Distant Horizons config
distanthorizons.config.client=Client
distanthorizons.config.client.quickEnableRendering=Enable Rendering
distanthorizons.config.client.quickEnableRendering.@tooltip=Determines if Distant Horizons Renders LODs.
distanthorizons.config.client.quickShowWorldGenProgress=Show LOD Gen/Import Progress
distanthorizons.config.client.quickShowWorldGenProgress.@tooltip=If true then the world gen/importing progress will be displayed on the screen when running.
distanthorizons.config.client.qualityPresetSetting=Quality Preset
distanthorizons.config.client.qualityPresetSetting.@tooltip=Modifies a number of graphical settings to quickly change Distant Horizons' rendering quality. \n\nLower this setting if your GPU is at max usage or you are having framerate issues.
distanthorizons.config.client.threadPresetSetting=CPU Load
distanthorizons.config.client.threadPresetSetting.@tooltip=Modifies how many threads Distant Horizons' will use. \n\nIncreasing this setting will improve the Distant Generator speed and LOD loading speed, \nbut will also increase CPU/memory usage and may introduce stuttering. \n\nNote: This is a CPU relative setting. \nIt should put an equal amount of strain on a 2 core CPU as a 64 core CPU.
distanthorizons.config.client.optionsButton=Show The Options Button
distanthorizons.config.client.optionsButton.@tooltip=Show the config button to the left of the fov button
distanthorizons.config.client.advanced=Advanced options
distanthorizons.config.client.advanced.graphics=Graphics
distanthorizons.config.client.advanced.worldGenerator=World Generator
distanthorizons.config.client.advanced.server=Server
distanthorizons.config.client.advanced.lodBuilding=LOD Building
distanthorizons.config.client.advanced.multiThreading=Multi-Threading
distanthorizons.config.client.advanced.logging=Logging
distanthorizons.config.client.advanced.graphics.quality=Quality
distanthorizons.config.client.advanced.graphics.quality.lodChunkRenderDistanceRadius=LOD Chunk Render Distance Radius
distanthorizons.config.client.advanced.graphics.quality.lodChunkRenderDistanceRadius.@tooltip=Distant Horizons' render distance, measured in chunks. \n\nNote: this is a best effort number. \nThe render distance may be above or below this number \ndepending on your other graphic settings.
distanthorizons.config.client.advanced.graphics.quality.horizontalQuality=LOD Dropoff Distance
distanthorizons.config.client.advanced.graphics.quality.horizontalQuality.@tooltip=How far apart drops in quality are.\n\nHigher settings will increase the distance between drops\nbut will increase memory and GPU usage.
distanthorizons.config.client.advanced.graphics.quality.maxHorizontalResolution=Max Horizontal Resolution
distanthorizons.config.client.advanced.graphics.quality.maxHorizontalResolution.@tooltip=The maximum detail LODs are rendered at.\n\n§6Fastest:§r Chunk\n§6Fanciest:§r Block
distanthorizons.config.client.advanced.graphics.quality.verticalQuality=Vertical Quality
distanthorizons.config.client.advanced.graphics.quality.verticalQuality.@tooltip=How well LODs represent overhangs, caves, cliffsides, etc.\n\nHigher options will increase memory and GPU usage.
distanthorizons.config.client.advanced.graphics.quality.horizontalScale=Horizontal Scale
distanthorizons.config.client.advanced.graphics.quality.horizontalScale.@tooltip=How quickly LODs drop off in quality.\n\nLarger numbers will improve how distant terrain looks\nbut will increase memory and GPU usage.
distanthorizons.config.client.advanced.graphics.quality.transparency=Transparency
distanthorizons.config.client.advanced.graphics.quality.blocksToIgnore=Blocks To Ignore
distanthorizons.config.client.advanced.graphics.quality.blocksToIgnore.@tooltip=Defines the types of blocks to ignore when generating LODs.
distanthorizons.config.client.advanced.graphics.quality.tintWithAvoidedBlocks=Tint With Avoided Blocks
distanthorizons.config.client.advanced.graphics.quality.tintWithAvoidedBlocks.@tooltip=§4Note: makes snow, carpet, and trapdoors look really bad§r\nShould the blocks underneath avoided blocks gain the color of the avoided block?\n§6True:§r a red flower on grass will tint the grass below it red\n§6False:§r skipped blocks will not change color of surface below them
distanthorizons.config.client.advanced.graphics.quality.lodShading=LOD Shading
distanthorizons.config.client.advanced.graphics.quality.lodShading.@tooltip=Defines how LODs should be shaded. \nCan be used to improve shader compatibility.
distanthorizons.config.client.advanced.graphics.quality.grassSideRendering=Grass Side Rendering
distanthorizons.config.client.advanced.graphics.quality.grassSideRendering.@tooltip=How should the sides and bottom of grass block LODs render?
distanthorizons.config.client.advanced.graphics.quality.ditherDhFade=Fade Nearby DH LODs
distanthorizons.config.client.advanced.graphics.quality.ditherDhFade.@tooltip=If true LODs will fade away as you get closer to them. \nIf false LODs will cut off abruptly at a set distance from the camera. \nThis setting is affected by the vanilla overdraw prevention config.
distanthorizons.config.client.advanced.graphics.quality.vanillaFadeMode=Vanilla Fade Mode
distanthorizons.config.client.advanced.graphics.quality.vanillaFadeMode.@tooltip=How should vanilla Minecraft fade into Distant Horizons LODs? \n\nNONE: Fastest, there will be a pronounced border between DH and MC rendering. \nSINGLE_PASS: Fades after MC's transparent pass, opaque blocks underwater won't be faded. \nDOUBLE_PASS: Slowest, fades after both MC's opaque and transparent passes, provides the smoothest transition.
distanthorizons.config.client.advanced.graphics.quality.dhFadeFarClipPlane=Fade Before Far Clip Plane
distanthorizons.config.client.advanced.graphics.quality.dhFadeFarClipPlane.@tooltip=Should DH fade out before reaching the far plane? \nThis is helpful to prevent DH clouds from cutting off in the distance.
distanthorizons.config.client.advanced.graphics.quality.brightnessMultiplier=Brightness Multiplier
distanthorizons.config.client.advanced.graphics.quality.brightnessMultiplier.@tooltip=How bright LOD colors are.\n\n0 = black \n1 = normal \n2 = near white
distanthorizons.config.client.advanced.graphics.quality.saturationMultiplier=Saturation Multiplier
distanthorizons.config.client.advanced.graphics.quality.saturationMultiplier.@tooltip=How saturated LOD colors are.\n\n0 = black and white \n1 = normal \n2 = vibrant
distanthorizons.config.client.advanced.graphics.quality.lodBiomeBlending=Biome Blending
distanthorizons.config.client.advanced.graphics.quality.lodBiomeBlending.@tooltip=This is the same as vanilla Biome Blending settings for LOD area. \n\nNote that anything other than '0' will greatly effect Lod building time\nand increase triangle count. The cost on chunk generation speed is also \nquite large if set to too high.\n\n'0' equals to Vanilla Biome Blending of '1x1', \n'1' equals to Vanilla Biome Blending of '3x3', \n'2' equals to Vanilla Biome Blending of '5x5'... \n
distanthorizons.config.client.advanced.graphics.ssao=Ambient Occlusion
distanthorizons.config.client.advanced.graphics.ssao.enableSsao=Enable Ambient Occlusion
distanthorizons.config.client.advanced.graphics.ssao.enableSsao.@tooltip=Ambient Occlusion adds depth to the lighting of blocks.
distanthorizons.config.client.advanced.graphics.ssao.sampleCount=Sample Count
distanthorizons.config.client.advanced.graphics.ssao.sampleCount.@tooltip=Determines how many points in space are sampled for the occlusion test. \nHigher numbers will improve quality and reduce banding, but will increase GPU load.
distanthorizons.config.client.advanced.graphics.ssao.radius=Radius
distanthorizons.config.client.advanced.graphics.ssao.radius.@tooltip=Determines the radius Screen Space Ambient Occlusion is applied, measured in blocks.
distanthorizons.config.client.advanced.graphics.ssao.strength=Strength
distanthorizons.config.client.advanced.graphics.ssao.strength.@tooltip=Determines how dark the Screen Space Ambient Occlusion effect will be.
distanthorizons.config.client.advanced.graphics.ssao.bias=Bias
distanthorizons.config.client.advanced.graphics.ssao.bias.@tooltip=Increasing the value can reduce banding at the cost of reducing the strength of the effect.
distanthorizons.config.client.advanced.graphics.ssao.minLight=Min Light
distanthorizons.config.client.advanced.graphics.ssao.minLight.@tooltip=Determines how dark the occlusion shadows can be. \n0 = totally black at the corners \n1 = no shadow
distanthorizons.config.client.advanced.graphics.ssao.blurRadius=Blur Radius
distanthorizons.config.client.advanced.graphics.ssao.blurRadius.@tooltip=The radius, measured in pixels, that blurring is calculated for the SSAO. \nHigher numbers will reduce banding at the cost of GPU performance.
distanthorizons.config.client.advanced.graphics.ssao.fadeDistanceInBlocks=Fade Distance
distanthorizons.config.client.advanced.graphics.ssao.fadeDistanceInBlocks.@tooltip=The distance in blocks from the camera where the SSAO will fade out to. \nThis is done to prevent banding and noise at extreme distances.
distanthorizons.config.client.advanced.graphics.genericRendering=Generic Object Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.enableGenericRendering=Enable Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.enableGenericRendering.@tooltip=If true non terrain objects will be rendered in DH's terrain. \nThis includes beacon beams and clouds.
distanthorizons.config.client.advanced.graphics.genericRendering.enableBeaconRendering=Enable Beacon Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.beaconRenderHeight=Beacon render height
distanthorizons.config.client.advanced.graphics.genericRendering.beaconRenderHeight.@tooltip=Sets the maximum height at which beacons will render. \nThis will only affect new beacons coming into LOD render distance. \nBeacons currently visible in LOD chunks will not be affected.
distanthorizons.config.client.advanced.graphics.genericRendering.expandDistantBeacons=Expand Distant Beacons
distanthorizons.config.client.advanced.graphics.genericRendering.expandDistantBeacons.@tooltip=If true LOD beacon beams will be rendered wider at extreme distances, \nmaking them easier to see. \nIf false all LOD beacon beams will only ever be 1 block wide.
distanthorizons.config.client.advanced.graphics.genericRendering.enableBeaconRendering.@tooltip=If true LOD beacon beams will be rendered.
distanthorizons.config.client.advanced.graphics.genericRendering.enableCloudRendering=Enable Cloud Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.enableCloudRendering.@tooltip=If true LOD clouds will be rendered.
distanthorizons.config.client.advanced.graphics.genericRendering.dimensionEnabledCloudRenderingCsv=Enable Cloud Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.dimensionEnabledCloudRenderingCsv.@tooltip=A comma separated separated list of dimension resource locations where DH clouds will render. \n\nExample: \minecraft:overworld,minecraft:the_end\ \n\nChanges will only be seen when the world is re-loaded.
distanthorizons.config.client.advanced.graphics.genericRendering.enableUnexploredFogRendering=Enable Unexplored Fog Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.enableUnexploredFogRendering.@tooltip=If true unexplored/ungenerated LODs will be rendered as large dark gray boxes.
distanthorizons.config.client.advanced.graphics.genericRendering.enableInstancedRendering=Enable Instanced Rendering
distanthorizons.config.client.advanced.graphics.genericRendering.enableInstancedRendering.@tooltip=Can be disabled to use much slower but more compatible direct rendering. \nDisabling this can be used to fix some crashes on Mac.
distanthorizons.config.client.advanced.graphics.fog=Fog
distanthorizons.config.client.advanced.graphics.fog.enableDhFog=Enable Distant Horizons Fog
distanthorizons.config.client.advanced.graphics.fog.enableDhFog.@tooltip=Determines if fog is drawn on DH LODs.
distanthorizons.config.client.advanced.graphics.fog.colorMode=Fog Color Mode
distanthorizons.config.client.advanced.graphics.fog.colorMode.@tooltip=The color of the fog on LODs.
distanthorizons.config.client.advanced.graphics.fog.enableVanillaFog=Enable Vanilla Fog
distanthorizons.config.client.advanced.graphics.fog.enableVanillaFog.@tooltip=§6True:§r Minecraft renders fog like normal.\n§6False:§r disables Minecraft's fog on vanilla chunks.\n\nMay cause issues with other mods that edit fog.
distanthorizons.config.client.advanced.graphics.fog.advancedFog=Advanced Fog Options
distanthorizons.config.client.advanced.graphics.fog.farFogStart=Fog Start
distanthorizons.config.client.advanced.graphics.fog.farFogStart.@tooltip=Where should the fog start? \n\n'0.0': Fog start at player's position.\n'1.0': The fog-start's circle fit just in the lod render distance square.\n'1.414': The lod render distance square fit just in the fog-start's circle.\n
distanthorizons.config.client.advanced.graphics.fog.farFogEnd=Fog End
distanthorizons.config.client.advanced.graphics.fog.farFogEnd.@tooltip=Where should the fog end? \n\n'0.0': Fog end at player's position.\n'1.0': The fog-end's circle fit just in the lod render distance square.\n'1.414': The lod render distance square fit just in the fog-end's circle.\n
distanthorizons.config.client.advanced.graphics.fog.farFogMin=Fog Min
distanthorizons.config.client.advanced.graphics.fog.farFogMin.@tooltip=What is the minimum fog thickness? \n\n'0.0': No fog at all.\n'1.0': Fully fog color.\n
distanthorizons.config.client.advanced.graphics.fog.farFogMax=Fog Max
distanthorizons.config.client.advanced.graphics.fog.farFogMax.@tooltip=What is the maximum fog thickness? \n\n'0.0': No fog at all.\n'1.0': Fully fog color.\n
distanthorizons.config.client.advanced.graphics.fog.farFogFalloff=Fog Falloff
distanthorizons.config.client.advanced.graphics.fog.farFogFalloff.@tooltip=How should the fog thickness should be calculated? \n\nLINEAR: Linear based on distance (will ignore 'density')\nEXPONENTIAL: 1/(e^(distance*density)) \nEXPONENTIAL_SQUARED: 1/(e^((distance*density)^2)) \n
distanthorizons.config.client.advanced.graphics.fog.farFogDensity=Fog Density
distanthorizons.config.client.advanced.graphics.fog.farFogDensity.@tooltip=What is the fog's density?
distanthorizons.config.client.advanced.graphics.fog.heightFog=Height Fog Options
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMixMode=Height Fog Mix Mode
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMixMode.@tooltip=Defines how height effects fog. \nWhen in doubt start with SPHERICAL, ADDITION, or MAX. \n\nSPHERICAL: Fog is calculated based on camera distance. \nCYLINDRICAL: Ignore height, fog is calculated based on horizontal distance. \nMAX: max(heightFog, farFog) \nADDITION: heightFog + farFog \nMULTIPLY: heightFog * farFog \nINVERSE_MULTIPLY: 1 - (1-heightFog) * (1-farFog) \nLIMITED_ADDITION: farFog + max(farFog, heightFog) \nMULTIPLY_ADDITION: farFog + farFog * heightFog \nINVERSE_MULTIPLY_ADDITION: farFog + 1 - (1-heightFog) * (1-farFog) \nAVERAGE: farFog*0.5 + heightFog*0.5
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogDirection=Height Fog Direction
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogDirection.@tooltip=Where should the height fog be located? \n\nABOVE_CAMERA: Height fog starts from camera to the sky \nBELOW_CAMERA: Height fog starts from camera to the void \nABOVE_AND_BELOW_CAMERA: Height fog starts from camera to both the sky and the void \nABOVE_SET_HEIGHT: Height fog starts from a set height to the sky \nBELOW_SET_HEIGHT: Height fog starts from a set height to the void \nABOVE_AND_BELOW_SET_HEIGHT: Height fog starts from a set height to both the sky and the void \n
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogBaseHeight=Height Fog Base Height
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogBaseHeight.@tooltip=If the height fog is calculated around a set height, what is that height position?
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogStart=Height Fog Start
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogStart.@tooltip=How far the start of height fog should offset? \n\n'0.0': Fog start with no offset.\n'1.0': Fog start with offset of the entire world's height. (Include depth)\n
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogEnd=Height Fog End
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogEnd.@tooltip=How far the end of height fog should offset? \n\n'0.0': Fog end with no offset.\n'1.0': Fog end with offset of the entire world's height. (Include depth)\n
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMin=Height Fog Min
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMin.@tooltip=What is the minimum fog thickness? \n\n'0.0': No fog at all.\n'1.0': Fully fog color.\n
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMax=Height Fog Max
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMax.@tooltip=What is the maximum fog thickness? \n\n'0.0': No fog at all.\n'1.0': Fully fog color.\n
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogFalloff=Height Fog Falloff
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogFalloff.@tooltip=How should the height fog thickness should be calculated? \n\nLINEAR: Linear based on height (will ignore 'density')\nEXPONENTIAL: 1/(e^(height*density)) \nEXPONENTIAL_SQUARED: 1/(e^((height*density)^2)) \n
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogDensity=Height Fog Density
distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogDensity.@tooltip=What is the height fog's density?
distanthorizons.config.client.advanced.graphics.noiseTexture=Noise Texture
distanthorizons.config.client.advanced.graphics.noiseTexture.enableNoiseTexture=Enable Noise Texture
distanthorizons.config.client.advanced.graphics.noiseTexture.enableNoiseTexture.@tooltip=If enabled a noise texture will be applied to LODs to simulate textures.
distanthorizons.config.client.advanced.graphics.noiseTexture.noiseSteps=Noise Steps
distanthorizons.config.client.advanced.graphics.noiseTexture.noiseSteps.@tooltip=Determines how many steps of noise should be applied to the LODs.
distanthorizons.config.client.advanced.graphics.noiseTexture.noiseIntensity=Noise Intensity
distanthorizons.config.client.advanced.graphics.noiseTexture.noiseIntensity.@tooltip=Determines how intense the noise texture is.
distanthorizons.config.client.advanced.graphics.noiseTexture.noiseDropoff=Noise Dropoff
distanthorizons.config.client.advanced.graphics.noiseTexture.noiseDropoff.@tooltip=Defines how far should the noise texture render before it fades away. (in blocks). \nSet to 0 to disable noise from fading away.
distanthorizons.config.client.advanced.graphics.culling=Culling
distanthorizons.config.client.advanced.graphics.culling.overdrawPrevention=Overdraw Prevention
distanthorizons.config.client.advanced.graphics.culling.overdrawPrevention.@tooltip=Determines how far from the camera Distant Horizons will start rendering. \nMeasured as a percentage of the vanilla render distance.\n-1 = Auto, overdraw will change based on the vanilla render distance.\n\nHigher values will prevent LODs from rendering behind vanilla blocks at a higher distance,\nbut may cause holes to appear in the LODs. \nHoles are most likely to appear when flying through unloaded terrain. \n\nIncreasing the vanilla render distance increases the effectiveness of this setting.
distanthorizons.config.client.advanced.graphics.culling.reduceOverdrawWithFastMovement=Reduce Overdraw With Fast Movement
distanthorizons.config.client.advanced.graphics.culling.reduceOverdrawWithFastMovement.@tooltip=If set to true the overdraw prevention radius will get closer \nto the camera when flying/moving quickly. \n\nThis helps reduce issues where Minecraft can't load or \ngenerate chunks fast enough to keep up with DH.
distanthorizons.config.client.advanced.graphics.culling.enableCaveCulling=Cave Culling
distanthorizons.config.client.advanced.graphics.culling.enableCaveCulling.@tooltip=If enabled caves will be culled \n\nAdditional Info: Currently this cull all faces \n with skylight value of 0 under the cave culling height in dimensions that \n do not have a ceiling. \n
distanthorizons.config.client.advanced.graphics.culling.caveCullingHeight=Cave Culling Height
distanthorizons.config.client.advanced.graphics.culling.caveCullingHeight.@tooltip=At what Y value should cave culling start?
distanthorizons.config.client.advanced.graphics.culling.disableBeaconDistanceCulling=Enable Beacon Distance Culling
distanthorizons.config.client.advanced.graphics.culling.disableBeaconDistanceCulling.@tooltip=If true beacons near the camera won't be drawn to prevent vanilla overdraw. \nIf false all beacons will be rendered.
distanthorizons.config.client.advanced.graphics.culling.disableFrustumCulling=Disable Frustum Culling
distanthorizons.config.client.advanced.graphics.culling.disableFrustumCulling.@tooltip=If false LODs outside the player's camera \naren't drawn, increasing GPU performance. \n\nIf true all LODs are drawn, even those behind \nthe player's camera, decreasing GPU performance. \n\nDisable this if you see LODs disappearing at the corners of your vision.
distanthorizons.config.client.advanced.graphics.culling.disableShadowPassFrustumCulling=Disable Shadow Pass Frustum Culling
distanthorizons.config.client.advanced.graphics.culling.disableShadowPassFrustumCulling.@tooltip=Identical to the other frustum culling option except that it is \nonly used when a shader mod is present using the DH API \nand the shadow pass is being rendered. \n\nDisable this if shadows render incorrectly.
distanthorizons.config.client.advanced.graphics.culling.ignoredRenderBlockCsv=Ignored Block CSV
distanthorizons.config.client.advanced.graphics.culling.ignoredRenderBlockCsv.@tooltip=A comma separated list of block resource locations that won't be rendered by DH. \nNote: air is always included in this list.
distanthorizons.config.client.advanced.graphics.culling.ignoredRenderCaveBlockCsv=Ignored Cave Block CSV
distanthorizons.config.client.advanced.graphics.culling.ignoredRenderCaveBlockCsv.@tooltip=A comma separated list of block resource locations that shouldn't be rendered \nif they are in a 0 sky light underground area. \nNote: air is always included in this list.
distanthorizons.config.client.advanced.graphics.overrideVanillaGraphicsSettings=Override Vanilla Settings
distanthorizons.config.client.advanced.graphics.overrideVanillaGraphicsSettings.@tooltip=If true some vanilla graphics settings will be automatically changed \nduring DH setup to provide a better experience. \n\nIE disabling vanilla clouds (which render on top of DH LODs), \nand chunk fading (DH already fades MC chunks).
distanthorizons.config.client.advanced.graphics.experimental=Experimental
distanthorizons.config.client.advanced.graphics.experimental.earthCurveRatio=Earth Curve Ratio
distanthorizons.config.client.advanced.graphics.experimental.earthCurveRatio.@tooltip=A value of 1 is equivalent to the curvature of Earth in real life. \nThe minimum accepted value is 50 and the maximum value is 5000. \nEverything between 1 and 49 will be rounded up to 50.
distanthorizons.config.client.advanced.graphics.experimental.ignoredDimensionCsv=Ignored Dimension CSV
distanthorizons.config.client.advanced.graphics.experimental.ignoredDimensionCsv.@tooltip=A comma separated list of dimension resource locations where DH won't render. Example: \minecraft:the_nether,minecraft:the_end\ \n\nNote: \nSome DH settings will be disabled and/or changed to improve \nvisuals when DH rendering is disabled.
distanthorizons.config.client.advanced.autoUpdater=Auto Updater
distanthorizons.config.client.advanced.autoUpdater.enableAutoUpdater=Enable automatic updates
distanthorizons.config.client.advanced.autoUpdater.enableSilentUpdates=Enable Silent Updates
distanthorizons.config.client.advanced.autoUpdater.enableSilentUpdates.@tooltip=Automatically updates the mod when an update is available
distanthorizons.config.client.advanced.autoUpdater.updateBranch=Update Branch
distanthorizons.config.client.advanced.autoUpdater.updateBranch.@tooltip=Where to download the latest update from. \n\nAuto: Downloads either stable or nightly builds based on the current jar. \nStable: Stable builds from Modrinth. \nNightly: Nightly builds from Gitlab.
distanthorizons.config.client.advanced.multiplayer=Multiplayer
distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode=Server Folder Mode
distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode.@tooltip=Determines the folder format for local multiplayer data.\n\n§6Name Only:§r\nUses the server browser name. Ex: \Minecraft Server\\n§6IP Only:§r\n\192.168.1.40\\n§6Name IP:§r\n\Minecraft Server, IP 192.168.1.40\\n§6Name, IP, Port:§r\n\Minecraft Server, IP 192.168.1.40:25565\\n§6Name, IP, Port, MC Version:§r\n\Minecraft Server, IP 192.168.1.40:25565, GameVersion 1.18.1\\n\n§c§lCaution:§r changing while connected to a multiplayer server may cause glitches.
distanthorizons.config.client.advanced.debugging=Debug
distanthorizons.config.client.advanced.debugging.rendererMode=Renderer Mode
distanthorizons.config.client.advanced.debugging.debugRendering=Debug Rendering
distanthorizons.config.client.advanced.debugging.lodOnlyMode=Only Render LODs
distanthorizons.config.client.advanced.debugging.lodOnlyMode.@tooltip=If enabled this will disable (most) vanilla Minecraft rendering. \n\nNOTE: Do not report any issues when this mode is on! \nThis setting is only for fun and debugging. \nMod compatibility is not guaranteed.
distanthorizons.config.client.advanced.debugging.renderWireframe=Render Wireframe
distanthorizons.config.client.advanced.debugging.renderWireframe.@tooltip=If enabled the LODs will render as wireframe.
distanthorizons.config.client.advanced.debugging.enableDebugKeybindings=Enable debug keybindings
distanthorizons.config.client.advanced.debugging.enableDebugKeybindings.@tooltip=If true several keys can be used to toggle debug states. \nF6 - enable/disable LOD rendering \nF7 - enable/disable LOD only rendering \nF8 - cycle through the different debug rendering modes
distanthorizons.config.client.advanced.debugging.enableWhiteWorld=Enable white world
distanthorizons.config.client.advanced.debugging.enableWhiteWorld.@tooltip=If enabled, vertex color will not be passed.\nUseful for debugging shaders.
distanthorizons.config.client.advanced.debugging.showOverlappingQuadErrors=Show overlapping quad errors
distanthorizons.config.client.advanced.debugging.showOverlappingQuadErrors.@tooltip=If true overlapping quads will be rendered as bright red for easy identification. \nIf false the quads will be rendered normally.
distanthorizons.config.client.advanced.debugging.logBufferGarbageCollection=Log Buffer Garbage Collection
distanthorizons.config.client.advanced.debugging.logBufferGarbageCollection.@tooltip=If true OpenGL Buffer garbage collection will be logged \nthis also includes the number of live buffers.
distanthorizons.config.client.advanced.debugging.allowUnsafeValues=Allow Unsafe UI Values
distanthorizons.config.client.advanced.debugging.allowUnsafeValues.@tooltip=If enabled, very limited config input validation will be performed. \n\nWarning: enabling this can cause instability or crashing, use at your own risk. \nNote: this option isn't saved between sessions.
distanthorizons.config.client.advanced.debugging.debugWireframe=Debug Wireframe
distanthorizons.config.client.advanced.debugging.debugWireframe.enableRendering=Enable Debug Wireframe Rendering
distanthorizons.config.client.advanced.debugging.debugWireframe.enableRendering.@tooltip=If enabled, various wireframes for debugging internal functions will be drawn.
distanthorizons.config.client.advanced.debugging.debugWireframe.showWorldGenQueue=Show World Gen Queue
distanthorizons.config.client.advanced.debugging.debugWireframe.showNetworkSyncOnLoadQueue=Show Network Sync On Load Queue
distanthorizons.config.client.advanced.debugging.debugWireframe.showRenderSectionStatus=Show Render Section Status
distanthorizons.config.client.advanced.debugging.debugWireframe.showRenderSectionToggling=Show Render Section Toggling
distanthorizons.config.client.advanced.debugging.debugWireframe.showQuadTreeRenderStatus=Show Quad Tree Render Status
distanthorizons.config.client.advanced.debugging.debugWireframe.showFullDataUpdateStatus=Show Full Data Update Status
distanthorizons.config.client.advanced.debugging.openGl=Open GL
distanthorizons.config.client.advanced.debugging.openGl.overrideVanillaGLLogger=Override Vanilla GL Logger
distanthorizons.config.client.advanced.debugging.openGl.overrideVanillaGLLogger.@tooltip=Defines how OpenGL errors are handled. \nRequires rebooting Minecraft to change. \nWill catch OpenGL errors thrown by other mods.
distanthorizons.config.client.advanced.debugging.openGl.onlyLogGlErrorsOnce=Only Log GL Errors Once
distanthorizons.config.client.advanced.debugging.openGl.onlyLogGlErrorsOnce.@tooltip=If true each Open GL error will only be logged once. \nTEnabling this may cause some error logs to be missed. \nDoes nothing if overrideVanillaGLLogger is set to false. \n\nGenerally this can be kept as 'true' to prevent log spam. \nHowever, Please set this to 'false' if a developer needs your log to debug a GL issue. \n
distanthorizons.config.client.advanced.debugging.openGl.glErrorHandlingMode=OpenGL Error Handling Mode
distanthorizons.config.client.advanced.debugging.openGl.glErrorHandlingMode.@tooltip=Defines how OpenGL errors are handled. \n Requires rebooting Minecraft to apply. \nMay incorrectly catch OpenGL errors thrown by other mods.
distanthorizons.config.client.advanced.debugging.openGl.validateBufferIdsBeforeRendering=Validate Buffer IDs Before Rendering
distanthorizons.config.client.advanced.debugging.openGl.validateBufferIdsBeforeRendering.@tooltip=Massively reduces FPS. \nShould only be used if mysterious EXCEPTION_ACCESS_VIOLATION crashes are happening in DH's rendering code and you're attempting to troubleshoot it.
distanthorizons.config.client.advanced.debugging.openGl.glUploadMode=Uploade Mode
distanthorizons.config.client.advanced.debugging.openGl.glUploadMode.@tooltip=Only for debugging
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging=Render Column Builder
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugEnable=Enable Column Builder Limiting
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugDetailLevel=Column Builder Limit - Detail Level
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugXPos=Column Builder Limit - X Pos
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugZPos=Column Builder Limit - Z Pos
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugXRow=Column Builder Limit - X Row
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugZRow=Column Builder Limit - Z Row
distanthorizons.config.client.advanced.debugging.columnBuilderDebugging.columnBuilderDebugColumnIndex=Column Builder Limit - Col Index
distanthorizons.config.client.advanced.debugging.f3Screen=F3 Screen
distanthorizons.config.client.advanced.debugging.f3Screen.showPlayerPos=Show Player Pos
distanthorizons.config.client.advanced.debugging.f3Screen.playerPosSectionDetailLevel=Player Section Pos Detail Level
distanthorizons.config.client.advanced.debugging.f3Screen.showThreadPools=Show Thread Pools
distanthorizons.config.client.advanced.debugging.f3Screen.showCombinedObjectPools=Show Combined Object Pools
distanthorizons.config.client.advanced.debugging.f3Screen.showSeparatedObjectPools=Show Separated Object Pools
distanthorizons.config.client.advanced.debugging.f3Screen.showQueuedChunkUpdateCount=Show Queued Chunk Update Count
distanthorizons.config.client.advanced.debugging.f3Screen.showLevelStatus=Show Level Status
distanthorizons.config.client.advanced.debugging.f3Screen.onlyShowRenderingLevels=Only Show Rendering Levels
distanthorizons.config.client.advanced.debugging.exampleConfigScreen=Debug Config Screen
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.debugConfigScreenNote=This screen is to debug features of the config screen
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.boolTest=Boolean test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.byteTest=Byte test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.intTest=Integer test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.doubleTest=Double test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.shortTest=Short test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.longTest=Long test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.floatTest=Float test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.stringTest=String test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.uiButtonTest=UI Button test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.listTest=List (ArrayList) test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.mapTest=Map (HashMap) test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.categoryTest=Category test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.linkableTest=Linkable test
distanthorizons.config.client.advanced.debugging.exampleConfigScreen.linkableTest.@tooltip=The value of this should be the same as in Category Test
distanthorizons.config.common=Common
distanthorizons.config.common.worldGenerator=World Generator
distanthorizons.config.common.worldGenerator.enableDistantGeneration=Enable Distant Generation
distanthorizons.config.common.worldGenerator.enableDistantGeneration.@tooltip=§6True:§r in single player LODs will be created outside the vanilla render distance.\nDepending on the Generator Mode pre-existing chunks will be important and/o\nmissing chunks will be generated.\nNote: this can use a large amount of CPU.\n\n§6False:§r LODs will only generate within the vanilla render distance.
distanthorizons.config.common.worldGenerator.distantGeneratorMode=Distance Generator Mode
distanthorizons.config.common.worldGenerator.distantGeneratorMode.@tooltip=How complicated the generation should be when generating LODs outside the vanilla render distance.
distanthorizons.config.common.worldGenerator.showGenerationProgress=Show Generation Progress
distanthorizons.config.common.worldGenerator.showGenerationProgress.@tooltip=Determines how should distant generator progress be displayed.
distanthorizons.config.common.worldGenerator.generationProgressDisplayIntervalInSeconds=Progress Display Interval In Seconds
distanthorizons.config.common.worldGenerator.generationProgressDisplayIntervalInSeconds.@tooltip=Determines how long between progress update displays.
distanthorizons.config.common.worldGenerator.generationProgressDisableMessageDisplayTimeInSeconds=Seconds To Show Progress Hiding Instructions
distanthorizons.config.common.worldGenerator.generationProgressDisableMessageDisplayTimeInSeconds.@tooltip=For how many seconds should instructions for disabling the distant generator progress be displayed? \nSetting this to 0 hides the instructional message so the world gen progress is shown immediately when it starts.
distanthorizons.config.common.worldGenerator.generationProgressIncludeChunksPerSecond=Show Generation Speed in Chunks/Second
distanthorizons.config.common.worldGenerator.generationProgressIncludeChunksPerSecond.@tooltip=When logging generation progress also include the rate at which chunks \nare being generated. \nThis can be useful for troubleshooting performance.
distanthorizons.config.common.lodBuilding=Lod Building
distanthorizons.config.common.lodBuilding.disableUnchangedChunkCheck=Disable Unchanged Chunk Check
distanthorizons.config.common.lodBuilding.disableUnchangedChunkCheck.@tooltip=Disabling this check may fix issues where LODs aren't updated after\nblocks have been changed.\n
distanthorizons.config.common.lodBuilding.pullLightingForPregeneratedChunks=Pull Lighting For Pre-generated Chunks
distanthorizons.config.common.lodBuilding.pullLightingForPregeneratedChunks.@tooltip=If true LOD generation for pre-existing chunks will attempt to pull the lighting data \nsaved in Minecraft's Region files. \nIf false DH will pull in chunks without lighting and re-light them. \n\nSetting this to true will result in faster LOD generation \nfor already generated worlds, but is broken by most lighting mods. \n\nSet this to false if LODs are black.
distanthorizons.config.common.lodBuilding.assumePreExistingChunksAreFinished=Assume Pre-Existing Chunks Are Finished
distanthorizons.config.common.lodBuilding.assumePreExistingChunksAreFinished.@tooltip=Setting this to true may solve some issues when using DH with a pre-generated world.
distanthorizons.config.common.lodBuilding.dataCompression=Data Compression
distanthorizons.config.common.lodBuilding.dataCompression.@tooltip=What algorithm should be used to compress new LOD data? \nThis setting will only affect new or updated LOD data, \nany data already generated when this setting is changed will be \nunaffected until it needs to be re-written to the database. \n\nFastest: LZ4 \nHighest Compression: LZMA2
distanthorizons.config.common.lodBuilding.worldCompression=Lossy World Compression
distanthorizons.config.common.lodBuilding.worldCompression.@tooltip=How should block data be compressed when creating LOD data? \nThis setting will only affect new or updated LOD data, \nany data already generated when this setting is changed will be \nunaffected until it is modified or re-loaded. \n\nMost Accurate: Merge Same Blocks \nHighest Compression: Visually Equal
distanthorizons.config.common.lodBuilding.recalculateChunkHeightmaps=Recalculate Chunk Heightmaps
distanthorizons.config.common.lodBuilding.recalculateChunkHeightmaps.@tooltip=True: Recalculate chunk height maps before chunks can be used by DH. This can fix problems with worlds created by external tools. \nFalse: Assume any height maps handled by Minecraft are correct. \n\nFastest: False\nMost Compatible: True
distanthorizons.config.common.lodBuilding.showMigrationChatWarning=Log Migration In Chat
distanthorizons.config.common.lodBuilding.experimental=Experimental
distanthorizons.config.common.lodBuilding.experimental.upsampleLowerDetailLodsToFillHoles=Upsample Lower Detail LODs To Fill Holes
distanthorizons.config.common.lodBuilding.experimental.upsampleLowerDetailLodsToFillHoles.@tooltip=When active DH will attempt to fill missing LOD data \nwith any data that is present in the tree, preventing holes when moving \nwhen a N-sized generator (or server) is active. \n\n§6EXPERIMENTAL§r Will increase harddrive use and may cause rendering issues. \nSee the config file for more details.
distanthorizons.config.common.multiThreading=Multi-Threading
distanthorizons.config.common.multiThreading.numberOfThreads=NO. of threads
distanthorizons.config.common.multiThreading.numberOfThreads.@tooltip=How many threads DH will use.
distanthorizons.config.common.multiThreading.threadRunTimeRatio=Runtime % for threads
distanthorizons.config.common.multiThreading.threadPriority=Thread Priority
distanthorizons.config.common.multiThreading.threadPriority.@tooltip=What Java thread priority should DH's primary thread pools run with?\n\nYou probably don't need to change this unless you are also \nrunning C2ME and are seeing thread starvation in either C2ME or DH.
distanthorizons.config.common.logging=Logging
distanthorizons.config.common.logging.@tooltip=Controls how logging should be handled.
distanthorizons.config.common.logging.globalFileMaxLevel=Global File Max
distanthorizons.config.common.logging.globalChatMaxLevel=Global Chat Max
distanthorizons.config.common.logging.logWorldGenEventToFile=World Gen Events - File
distanthorizons.config.common.logging.logWorldGenPerformanceToFile=World Gen Performance - File
distanthorizons.config.common.logging.logWorldGenChunkLoadEventToFile=World Gen Load Events - File
distanthorizons.config.common.logging.logRendererEventToFile=Renderer Events - File
distanthorizons.config.common.logging.logRendererGLEventToFile=OpenGL Events - File
distanthorizons.config.common.logging.logRendererGLEventToChat=OpenGL Events - Chat
distanthorizons.config.common.logging.logNetworkEventToFile=Network Events - File
distanthorizons.config.common.logging.logConnectionConfigChangesToFile=Network Connection Config Changes - File
distanthorizons.config.common.logging.warning=Warnings
distanthorizons.config.common.logging.warning.showLowMemoryWarningOnStartup=Show Low Memory Warning On Startup
distanthorizons.config.common.logging.warning.showPoolInsufficientMemoryWarning=Show Pool Insufficient Memory Warning
distanthorizons.config.common.logging.warning.showPoolInsufficientMemoryWarning.@tooltip=If DH detects that pooled objects are being garbage collected this will send a chat warning.
distanthorizons.config.common.logging.warning.showHighVanillaRenderDistanceWarning=Show High Vanilla Render Distance Warning
distanthorizons.config.common.logging.warning.showReplayWarningOnStartup=Show Replay Warning
distanthorizons.config.common.logging.warning.showUpdateQueueOverloadedChatWarning=Show Update Queue Overloaded Warning
distanthorizons.config.common.logging.warning.showSlowWorldGenSettingWarnings=Show Slow World Gen Warnings
distanthorizons.config.common.logging.warning.showModCompatibilityWarningsOnStartup=Show Mod Compatibility Warnings
distanthorizons.config.common.logging.warning.showGarbageCollectorWarning=Show Garbage Collector Warning
distanthorizons.config.common.logging.warning.logGarbageCollectorWarning=Log Garbage Collector Warning
distanthorizons.config.server=Server
distanthorizons.config.server.sendLevelKeys=Send Level Keys
distanthorizons.config.server.sendLevelKeys.@tooltip=Makes the server send level keys for each world.\nDisable this if you use alternative ways to send level keys.
distanthorizons.config.server.levelKeyPrefix=Level Key Prefix
distanthorizons.config.server.levelKeyPrefix.@tooltip=Prefix of the level keys sent to the clients.\nIf the mod is running behind a proxy, each backend should use a unique value.\nIf this value is empty, level key will be based on the server's seed hash.
distanthorizons.config.server.enableServerGeneration=Enable Server Generation
distanthorizons.config.server.enableServerGeneration.@tooltip=When enabled, Distant Horizons will attempt to download missing LODs from the server.\n\nNote: the server must have Distant Generation enabled for it to work.
distanthorizons.config.server.generationRequestRateLimit=Rate Limit for Generation Requests
distanthorizons.config.server.generationRequestRateLimit.@tooltip=How many LOD generation requests per second should a client send?\nAlso limits the number of client requests allowed to stay in the server's queue.
distanthorizons.config.server.maxGenerationRequestDistance=Max Generation Request Distance
distanthorizons.config.server.maxGenerationRequestDistance.@tooltip=Defines the distance allowed to generate around the player.
distanthorizons.config.server.enableRealTimeUpdates=Enable Real-time Updates
distanthorizons.config.server.enableRealTimeUpdates.@tooltip=If true, clients will receive real-time LOD updates for chunks outside the client's render distance.
distanthorizons.config.server.realTimeUpdateDistanceRadiusInChunks=Real-time Update Radius in Chunks
distanthorizons.config.server.realTimeUpdateDistanceRadiusInChunks.@tooltip=Defines the distance the player will receive updates around.
distanthorizons.config.server.synchronizeOnLoad=Synchronize LODs on Load
distanthorizons.config.server.synchronizeOnLoad.@tooltip=If true, clients will receive updated LODs when joining or loading new LODs.
distanthorizons.config.server.syncOnLoadRateLimit=Rate Limit for Sync on Load
distanthorizons.config.server.syncOnLoadRateLimit.@tooltip=How many LOD sync requests per second should a client send?\nAlso limits the number of client's requests allowed to stay in the server's queue.
distanthorizons.config.server.maxSyncOnLoadRequestDistance=Max Sync on Load Request Distance
distanthorizons.config.server.maxSyncOnLoadRequestDistance.@tooltip=Defines the distance allowed to be synchronized around the player.\nShould be the same or larger than maxGenerationRequestDistance in most cases.
distanthorizons.config.server.playerBandwidthLimit=Per-player Bandwidth Limit, KB/s
distanthorizons.config.server.playerBandwidthLimit.@tooltip=Maximum per-player speed for uploading LODs to the clients, in KB/s.\nValue of 0 disables the limit.
distanthorizons.config.server.globalBandwidthLimit=Global Bandwidth Limit, KB/s
distanthorizons.config.server.globalBandwidthLimit.@tooltip=Maximum global speed for uploading LODs to the clients, in KB/s.\nValue of 0 disables the limit.
distanthorizons.config.server.enableAdaptiveTransferSpeed=Enable Adaptive Transfer Speed
distanthorizons.config.server.enableAdaptiveTransferSpeed.@tooltip=Enables adaptive transfer speed based on client performance.\nIf true, DH will automatically adjust transfer rate to minimize connection lag.\nIf false, transfer speed will remain fixed.
distanthorizons.config.server.experimental=Experimental
distanthorizons.config.server.experimental.enableNSizedGeneration=Enable N-sized generation
distanthorizons.config.server.experimental.enableNSizedGeneration.@tooltip=When enabled on the client, this allows loading lower detail levels as needed to speed up terrain generation.\nThis must also be enabled on the server; otherwise, it will have no effect.\nFor better performance when switching LOD detail levels, enabling [upsampleLowerDetailLodsToFillHoles] is recommended.
distanthorizons.config.enum.EDhApiQualityPreset.CUSTOM=Custom
distanthorizons.config.enum.EDhApiQualityPreset.MINIMUM=1. Minimum
distanthorizons.config.enum.EDhApiQualityPreset.LOW=2. Low
distanthorizons.config.enum.EDhApiQualityPreset.MEDIUM=3. Medium
distanthorizons.config.enum.EDhApiQualityPreset.HIGH=4. High
distanthorizons.config.enum.EDhApiQualityPreset.EXTREME=5. Extreme
distanthorizons.config.enum.EDhApiThreadPreset.CUSTOM=Custom
distanthorizons.config.enum.EDhApiThreadPreset.MINIMAL_IMPACT=1. Minimal Impact
distanthorizons.config.enum.EDhApiThreadPreset.LOW_IMPACT=2. Low Impact
distanthorizons.config.enum.EDhApiThreadPreset.BALANCED=3. Balanced
distanthorizons.config.enum.EDhApiThreadPreset.AGGRESSIVE=4. Aggressive
distanthorizons.config.enum.EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU=5. I Paid For The Whole CPU
distanthorizons.config.enum.EDhApiMaxHorizontalResolution.BLOCK=1. Block
distanthorizons.config.enum.EDhApiMaxHorizontalResolution.TWO_BLOCKS=2. 2 blocks
distanthorizons.config.enum.EDhApiMaxHorizontalResolution.FOUR_BLOCKS=3. 4 blocks
distanthorizons.config.enum.EDhApiMaxHorizontalResolution.HALF_CHUNK=4. Half a chunk
distanthorizons.config.enum.EDhApiMaxHorizontalResolution.CHUNK=5. Chunk
distanthorizons.config.enum.EDhApiMcRenderingFadeMode.NONE=None
distanthorizons.config.enum.EDhApiMcRenderingFadeMode.SINGLE_PASS=Single Pass
distanthorizons.config.enum.EDhApiMcRenderingFadeMode.DOUBLE_PASS=Double Pass
distanthorizons.config.enum.EDhApiVerticalQuality.HEIGHT_MAP=1. Height Map
distanthorizons.config.enum.EDhApiVerticalQuality.LOW=2. Low
distanthorizons.config.enum.EDhApiVerticalQuality.MEDIUM=3. Medium
distanthorizons.config.enum.EDhApiVerticalQuality.HIGH=4. High
distanthorizons.config.enum.EDhApiVerticalQuality.VERY_HIGH=5. Very High
distanthorizons.config.enum.EDhApiVerticalQuality.EXTREME=6. Extreme
distanthorizons.config.enum.EDhApiVerticalQuality.PIXEL_ART=7. Pixel Art
distanthorizons.config.enum.EDhApiHorizontalQuality.LOWEST=Lowest
distanthorizons.config.enum.EDhApiHorizontalQuality.LOW=Low
distanthorizons.config.enum.EDhApiHorizontalQuality.MEDIUM=Medium
distanthorizons.config.enum.EDhApiHorizontalQuality.HIGH=High
distanthorizons.config.enum.EDhApiHorizontalQuality.EXTREME=Extreme
distanthorizons.config.enum.EDhApiTransparency.DISABLED=Disabled
distanthorizons.config.enum.EDhApiTransparency.FAKE=Fake
distanthorizons.config.enum.EDhApiTransparency.COMPLETE=Complete
distanthorizons.config.enum.EDhApiFogDrawMode.USE_OPTIFINE_SETTING=Use modded settings
distanthorizons.config.enum.EDhApiFogDrawMode.FOG_ENABLED=Enabled
distanthorizons.config.enum.EDhApiFogDrawMode.FOG_DISABLED=Disabled
distanthorizons.config.enum.EDhApiFogColorMode.USE_WORLD_FOG_COLOR=Use world fog
distanthorizons.config.enum.EDhApiFogColorMode.USE_SKY_COLOR=Use sky color
distanthorizons.config.enum.EDhApiFogFalloff.LINEAR=Linear
distanthorizons.config.enum.EDhApiFogFalloff.EXPONENTIAL=Exponential
distanthorizons.config.enum.EDhApiFogFalloff.EXPONENTIAL_SQUARED=Exponential squared
distanthorizons.config.enum.EDhApiHeightFogMixMode.SPHERICAL=Spherical
distanthorizons.config.enum.EDhApiHeightFogMixMode.CYLINDRICAL=Cylindrical
distanthorizons.config.enum.EDhApiHeightFogMixMode.ADDITION=Addition
distanthorizons.config.enum.EDhApiHeightFogMixMode.MAX=Max
distanthorizons.config.enum.EDhApiHeightFogMixMode.MULTIPLY=Multiply
distanthorizons.config.enum.EDhApiHeightFogMixMode.INVERSE_MULTIPLY=Inverse Multiply
distanthorizons.config.enum.EDhApiHeightFogMixMode.LIMITED_ADDITION=Limited Addition
distanthorizons.config.enum.EDhApiHeightFogMixMode.MULTIPLY_ADDITION=Multiply Addition
distanthorizons.config.enum.EDhApiHeightFogMixMode.INVERSE_MULTIPLY_ADDITION=Inverse Multiply Addition
distanthorizons.config.enum.EDhApiHeightFogMixMode.AVERAGE=Average
distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_CAMERA=Above Camera
distanthorizons.config.enum.EDhApiHeightFogDirection.BELOW_CAMERA=Below Camera
distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_AND_BELOW_CAMERA=Above And Below Camera
distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_SET_HEIGHT=Above Set Height
distanthorizons.config.enum.EDhApiHeightFogDirection.BELOW_SET_HEIGHT=Below Set Height
distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_AND_BELOW_SET_HEIGHT=Above And Below Set Height
distanthorizons.config.enum.EDhApiVanillaOverdraw.NEVER=Never
distanthorizons.config.enum.EDhApiVanillaOverdraw.DYNAMIC=Dynamic
distanthorizons.config.enum.EDhApiVanillaOverdraw.ALWAYS=Always
distanthorizons.config.enum.EDhApiDistantGeneratorMode.NONE=1. Existing Only
distanthorizons.config.enum.EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY=2. Pre-Existing Chunks only
distanthorizons.config.enum.EDhApiDistantGeneratorMode.BIOME_ONLY=3. Biome only
distanthorizons.config.enum.EDhApiDistantGeneratorMode.BIOME_ONLY_SIMULATE_HEIGHT=4. Biome only simulate height
distanthorizons.config.enum.EDhApiDistantGeneratorMode.SURFACE=5. Surface
distanthorizons.config.enum.EDhApiDistantGeneratorMode.FEATURES=6. Features
distanthorizons.config.enum.EDhApiDistantGeneratorMode.INTERNAL_SERVER=7. Full - Save Chunks
distanthorizons.config.enum.EDhApiDistantGeneratorProgressDisplayLocation.OVERLAY=Overlay
distanthorizons.config.enum.EDhApiDistantGeneratorProgressDisplayLocation.CHAT=Chat
distanthorizons.config.enum.EDhApiDistantGeneratorProgressDisplayLocation.LOG=Log
distanthorizons.config.enum.EDhApiDistantGeneratorProgressDisplayLocation.DISABLED=Disabled
distanthorizons.config.enum.EDhApiDataCompressionMode.UNCOMPRESSED=Uncompressed
distanthorizons.config.enum.EDhApiDataCompressionMode.LZ4=Fastest/Big - LZ4
distanthorizons.config.enum.EDhApiDataCompressionMode.Z_STD_BLOCK=Fastest/Small - Z_STD - Block
distanthorizons.config.enum.EDhApiDataCompressionMode.Z_STD_STREAM=Fast/Small - Z_STD - Stream
distanthorizons.config.enum.EDhApiDataCompressionMode.LZMA2=Slow/Smallest - LZMA2
distanthorizons.config.enum.EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS=1. Merge Same Blocks
distanthorizons.config.enum.EDhApiWorldCompressionMode.VISUALLY_EQUAL=2. Visually Equal
distanthorizons.config.enum.EDhApiBlocksToAvoid.NONE=None
distanthorizons.config.enum.EDhApiBlocksToAvoid.NON_COLLIDING=Non-Colliding
distanthorizons.config.enum.EDhApiServerFolderNameMode.NAME_ONLY=Name Only
distanthorizons.config.enum.EDhApiServerFolderNameMode.IP_ONLY=IP Only
distanthorizons.config.enum.EDhApiServerFolderNameMode.NAME_IP=Name and IP
distanthorizons.config.enum.EDhApiServerFolderNameMode.NAME_IP_PORT=Name, IP, Port
distanthorizons.config.enum.EDhApiServerFolderNameMode.NAME_IP_PORT_MC_VERSION=Name, IP, Port, MC version
distanthorizons.config.enum.EDhApiRendererMode.DEFAULT=Default
distanthorizons.config.enum.EDhApiRendererMode.DEBUG=Debug
distanthorizons.config.enum.EDhApiRendererMode.DISABLED=Disabled
distanthorizons.config.enum.EDhApiDebugRendering.OFF=Off
distanthorizons.config.enum.EDhApiDebugRendering.SHOW_DETAIL=Show detail
distanthorizons.config.enum.EDhApiDebugRendering.SHOW_GENMODE=Show generation mode
distanthorizons.config.enum.EDhApiDebugRendering.SHOW_BLOCK_MATERIAL=Show Material
distanthorizons.config.enum.EDhApiDebugRendering.SHOW_OVERLAPPING_QUADS=Show overlapping quads
distanthorizons.config.enum.EDhApiDebugRendering.SHOW_RENDER_SOURCE_FLAG=Show render source flag
distanthorizons.config.enum.EDhApiGLErrorHandlingMode.IGNORE=Ignore
distanthorizons.config.enum.EDhApiGLErrorHandlingMode.LOG=Log
distanthorizons.config.enum.EDhApiGLErrorHandlingMode.LOG_THROW=Log-Throw
distanthorizons.config.enum.EDhApiGlProfileMode.CORE=Core
distanthorizons.config.enum.EDhApiGlProfileMode.COMPAT=Compat
distanthorizons.config.enum.EDhApiGlProfileMode.ANY=Any
distanthorizons.config.enum.EDhApiLoggerLevel.ALL=1. All
distanthorizons.config.enum.EDhApiLoggerLevel.DEBUG=2. Debug
distanthorizons.config.enum.EDhApiLoggerLevel.INFO=3. Info
distanthorizons.config.enum.EDhApiLoggerLevel.WARN=4. Warn
distanthorizons.config.enum.EDhApiLoggerLevel.ERROR=5. Error
distanthorizons.config.enum.EDhApiLoggerLevel.DISABLED=6. Disabled
distanthorizons.config.enum.EDhApiGpuUploadMethod.AUTO=Auto
distanthorizons.config.enum.EDhApiGpuUploadMethod.NONE=None
distanthorizons.config.enum.EDhApiGpuUploadMethod.BUFFER_STORAGE=Buffer storage
distanthorizons.config.enum.EDhApiGpuUploadMethod.SUB_DATA=Sub data
distanthorizons.config.enum.EDhApiGpuUploadMethod.BUFFER_MAPPING=Buffer mapping
distanthorizons.config.enum.EDhApiGpuUploadMethod.DATA=Data
distanthorizons.config.enum.EDhApiLodShading.AUTO=Auto
distanthorizons.config.enum.EDhApiLodShading.ENABLED=Enabled
distanthorizons.config.enum.EDhApiLodShading.DISABLED=Disabled
distanthorizons.config.enum.EDhApiUpdateBranch.STABLE=Stable
distanthorizons.config.enum.EDhApiUpdateBranch.NIGHTLY=Nightly
distanthorizons.config.enum.EDhApiUpdateBranch.AUTO=Auto
distanthorizons.config.enum.EDhApiGrassSideRendering.AS_GRASS=As Grass
distanthorizons.config.enum.EDhApiGrassSideRendering.FADE_TO_DIRT=Fade To Dirt
distanthorizons.config.enum.EDhApiGrassSideRendering.AS_DIRT=As Dirt
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="700pt"
height="700pt"
version="1.1"
viewBox="0 0 700 700"
id="svg4"
sodipodi:docname="themeDark.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="pt"
showgrid="false"
inkscape:zoom="0.79607143"
inkscape:cx="466.66667"
inkscape:cy="466.03858"
inkscape:window-width="2560"
inkscape:window-height="1351"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m573.12 450.62c-1.5625-3.2305-4.0781-5.9023-7.207-7.6562-3.1289-1.7539-6.7227-2.5-10.293-2.1445-52.113 7.4141-105.18-3.3867-150.25-30.578-45.07-27.191-79.371-69.105-97.113-118.66-17.738-49.555-17.832-103.71-0.25781-153.33 12.207-34.535 32.625-65.586 59.5-90.477 3.8047-3.4023 5.9336-8.3008 5.8242-13.406-0.10938-5.1055-2.4414-9.9102-6.3867-13.152-3.9453-3.2422-9.1094-4.5977-14.137-3.7148-55.062 7.5039-106.35 32.211-146.54 70.594s-67.223 88.48-77.246 143.14c-10.023 54.656-2.5273 111.09 21.422 161.23 23.949 50.145 63.129 91.441 111.94 118 48.816 26.559 104.77 37.016 159.89 29.883 55.109-7.1328 106.56-31.492 147-69.602 2.6758-2.5234 4.4883-5.8281 5.1797-9.4414 0.69141-3.6133 0.22656-7.3516-1.3281-10.684z"
id="path2"
style="fill:#003380" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="700pt"
height="700pt"
version="1.1"
viewBox="0 0 700 700"
id="svg22"
sodipodi:docname="themeLight.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs26" />
<sodipodi:namedview
id="namedview24"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="pt"
showgrid="false"
inkscape:zoom="0.79607143"
inkscape:cx="466.66667"
inkscape:cy="466.03858"
inkscape:window-width="2560"
inkscape:window-height="1351"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg22" />
<g
id="g20"
style="fill:#55d400">
<path
d="m472.5 280c0 67.656-54.844 122.5-122.5 122.5s-122.5-54.844-122.5-122.5 54.844-122.5 122.5-122.5 122.5 54.844 122.5 122.5"
id="path2"
style="fill:#55d400" />
<path
d="m350 140c4.6406 0 9.0938-1.8438 12.375-5.125s5.125-7.7344 5.125-12.375v-87.5c0-6.2539-3.3359-12.031-8.75-15.156s-12.086-3.125-17.5 0-8.75 8.9023-8.75 15.156v87.5c0 4.6406 1.8438 9.0938 5.125 12.375s7.7344 5.125 12.375 5.125z"
id="path4"
style="fill:#55d400" />
<path
d="m226.27 180.95c3.1719 3.7031 7.7461 5.918 12.617 6.1055 4.875 0.1875 9.6016-1.6641 13.051-5.1133 3.4492-3.4492 5.3008-8.1758 5.1133-13.051-0.1875-4.8711-2.4023-9.4453-6.1055-12.617l-61.773-61.949c-4.4414-4.4375-10.91-6.1719-16.973-4.5469-6.0664 1.625-10.801 6.3594-12.426 12.426-1.625 6.0625 0.10938 12.531 4.5469 16.973z"
id="path6"
style="fill:#55d400" />
<path
d="m210 280c0-4.6406-1.8438-9.0938-5.125-12.375s-7.7344-5.125-12.375-5.125h-87.5c-6.2539 0-12.031 3.3359-15.156 8.75s-3.125 12.086 0 17.5 8.9023 8.75 15.156 8.75h87.5c4.6406 0 9.0938-1.8438 12.375-5.125s5.125-7.7344 5.125-12.375z"
id="path8"
style="fill:#55d400" />
<path
d="m226.27 379.05-61.949 61.773c-3.7031 3.1719-5.9141 7.7461-6.1016 12.617-0.19141 4.8711 1.6641 9.6016 5.1094 13.051 3.4492 3.4453 8.1797 5.3008 13.051 5.1133 4.8711-0.19141 9.4453-2.4023 12.617-6.1055l61.949-61.949c3.8594-4.5078 5.1719-10.66 3.4922-16.348-1.6836-5.6875-6.1328-10.137-11.82-11.816-5.6875-1.6836-11.84-0.37109-16.348 3.4883z"
id="path10"
style="fill:#55d400" />
<path
d="m350 420c-4.6406 0-9.0938 1.8438-12.375 5.125s-5.125 7.7344-5.125 12.375v87.5c0 6.2539 3.3359 12.031 8.75 15.156s12.086 3.125 17.5 0 8.75-8.9023 8.75-15.156v-87.5c0-4.6406-1.8438-9.0938-5.125-12.375s-7.7344-5.125-12.375-5.125z"
id="path12"
style="fill:#55d400" />
<path
d="m473.73 379.05c-4.5078-3.8594-10.66-5.1719-16.348-3.4922-5.6875 1.6836-10.137 6.1328-11.82 11.82-1.6797 5.6875-0.36719 11.84 3.4922 16.348l61.949 61.949c4.5039 3.8555 10.656 5.1719 16.348 3.4883 5.6875-1.6797 10.137-6.1289 11.816-11.816 1.6836-5.6914 0.36719-11.844-3.4883-16.348z"
id="path14"
style="fill:#55d400" />
<path
d="m595 262.5h-87.5c-6.2539 0-12.031 3.3359-15.156 8.75s-3.125 12.086 0 17.5 8.9023 8.75 15.156 8.75h87.5c6.2539 0 12.031-3.3359 15.156-8.75s3.125-12.086 0-17.5-8.9023-8.75-15.156-8.75z"
id="path16"
style="fill:#55d400" />
<path
d="m461.3 186.2c4.6523 0.027343 9.1211-1.7969 12.426-5.0742l61.949-61.949c3.8555-4.5078 5.1719-10.66 3.4883-16.348-1.6797-5.6875-6.1289-10.137-11.816-11.816-5.6914-1.6836-11.844-0.37109-16.348 3.4883l-61.949 61.773c-3.3086 3.2852-5.1719 7.75-5.1758 12.414-0.003906 4.6602 1.8516 9.1289 5.1562 12.418 3.3047 3.2891 7.7812 5.1211 12.445 5.0938z"
id="path18"
style="fill:#55d400" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,10 @@
<?xml version="1.0" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<!-- No icon texture for DH -->
<rect width="50" height="50" x="0" y="0" style="fill:#0000FF" />
<rect width="50" height="50" x="50" y="50" style="fill:#0000FF" />
<rect width="50" height="50" x="50" y="0" style="fill:#000000" />
<rect width="50" height="50" x="0" y="50" style="fill:#000000" />
</svg>

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,19 @@
{
"required": true,
"package": "com.seibel.distanthorizons.cleanroom.mixins",
"compatibilityLevel": "JAVA_8",
"target": "@env(DEFAULT)",
"mixins": [
"common.MixinChunkProviderServer"
],
"minVersion": "0.8.7",
"server": [
"server.MixinEntityPlayerMP"
],
"client": [
"client.MixinEntityRenderer",
"client.MixinNetHandlerPlayClient",
"client.MixinOptionsScreen",
"client.MixinRenderGlobal"
]
}
@@ -0,0 +1,11 @@
{
"required": false,
"package": "com.seibel.distanthorizons.cleanroom.mixins.mod",
"compatibilityLevel": "JAVA_8",
"target": "@env(MOD)",
"mixins": [],
"minVersion": "0.8.7",
"plugin": "com.seibel.distanthorizons.cleanroom.DistantHorizonsConfigPlugin",
"client": [
]
}
@@ -0,0 +1,33 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D gDhColorTexture;
uniform sampler2D gDhDepthTexture;
/**
* LOD application shader
*
* This merges the rendered LODs into Minecraft's texture/FBO
*/
void main()
{
fragColor = vec4(0.0);
// a fragment depth of "1" means the fragment wasn't drawn to,
// only update fragments that were drawn to
float fragmentDepth = texture(gDhDepthTexture, TexCoord).r;
if (fragmentDepth != 1)
{
fragColor = texture(gDhColorTexture, TexCoord);
}
else
{
// use the original MC texture if no LODs were drawn to this fragment
discard;
}
}
@@ -0,0 +1,10 @@
#version 150 core
uniform vec4 uColor;
out vec4 fragColor;
void main()
{
fragColor = uColor;
}
@@ -0,0 +1,10 @@
#version 150 core
uniform mat4 uTransform;
in vec3 vPosition;
void main()
{
gl_Position = uTransform * vec4(vPosition, 1.0);
}
@@ -0,0 +1,14 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D uFadeColorTextureUniform;
void main()
{
fragColor = texture(uFadeColorTextureUniform, TexCoord);
}
@@ -0,0 +1,65 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
// inverted model view matrix and projection matrix
uniform mat4 uDhInvMvmProj;
uniform sampler2D uDhDepthTexture;
uniform sampler2D uMcColorTexture;
uniform sampler2D uDhColorTexture;
uniform float uStartFadeBlockDistance;
uniform float uEndFadeBlockDistance;
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// normalized device coordinates
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
ndc.xyz = ndc.xyz * 2.0 - 1.0;
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
/**
* Used to fade out vanilla chunks so the transition
* between DH and vanilla is smoother.
*/
void main()
{
// includes both the vanilla chunks as well as DH
vec4 combinedMcDhColor = texture(uMcColorTexture, TexCoord);
// just the DH render pass
vec4 dhColor = texture(uDhColorTexture, TexCoord);
// the DH texture will have white if nothing was written to that pixel.
if (dhColor == vec4(1))
{
// if not done vanilla clouds will render incorrectly at night
dhColor = combinedMcDhColor;
}
float dhFragmentDepth = texture(uDhDepthTexture, TexCoord).r;
vec3 dhVertexWorldPos = calcViewPosition(dhFragmentDepth, uDhInvMvmProj);
float dhFragmentDistance = length(dhVertexWorldPos.xzy);
float startFade = uEndFadeBlockDistance;
float endFade = uStartFadeBlockDistance;
// Smoothly transition between combinedMcDhColor and uDhColorTexture
// as the depth increases from the camera
float fadeStep = smoothstep(startFade, endFade, dhFragmentDistance);
fragColor = mix(combinedMcDhColor, dhColor, fadeStep);
fragColor.a = 1.0;
}
@@ -0,0 +1,91 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
// inverted model view matrix and projection matrix
uniform mat4 uDhInvMvmProj;
uniform mat4 uMcInvMvmProj;
uniform sampler2D uMcDepthTexture;
uniform sampler2D uDhDepthTexture;
uniform sampler2D uCombinedMcDhColorTexture;
uniform sampler2D uDhColorTexture;
uniform float uStartFadeBlockDistance;
uniform float uEndFadeBlockDistance;
uniform float uMaxLevelHeight;
uniform bool uOnlyRenderLods;
vec3 calcViewPosition(float fragmentDepth, mat4 invMvmProj)
{
// normalized device coordinates
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
ndc.xyz = ndc.xyz * 2.0 - 1.0;
vec4 eyeCoord = invMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
/**
* Used to fade out vanilla chunks so the transition
* between DH and vanilla is smoother.
*/
void main()
{
// includes both the vanilla chunks as well as DH
vec4 combinedMcDhColor = texture(uCombinedMcDhColorTexture, TexCoord);
// just the DH render pass
vec4 dhColor = texture(uDhColorTexture, TexCoord);
// completely remove the MC render pass to only show LODs
// useful for debugging/troubleshooting, but doesn't improve performance since MC is still rendering
if (uOnlyRenderLods)
{
fragColor = dhColor;
return;
}
// ignore anything that DH hasn't drawn to
// We don't use DH's depth here because it would prevent the fade from running before DH has loaded
if (dhColor == vec4(1))
{
// if not done vanilla clouds will render incorrectly at night
dhColor = combinedMcDhColor;
}
float mcFragmentDepth = texture(uMcDepthTexture, TexCoord).r;
float dhFragmentDepth = texture(uDhDepthTexture, TexCoord).r;
vec3 dhVertexWorldPos = calcViewPosition(dhFragmentDepth, uDhInvMvmProj);
// this is a work around to prevent MC clouds rendering behind DH clouds
if (dhVertexWorldPos.y > uMaxLevelHeight)
{
fragColor = vec4(combinedMcDhColor.rgb, 0.0);
}
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to fade vanilla rendered objects, not to the sky or LODs
else if (mcFragmentDepth < 1.0)
{
// fade based on distance from the camera
vec3 mcVertexWorldPos = calcViewPosition(mcFragmentDepth, uMcInvMvmProj);
float mcFragmentDistance = length(mcVertexWorldPos.xzy);
// Smoothly transition between combinedMcDhColor and uDhColorTexture
// as the depth increases from the camera
float fadeStep = smoothstep(uStartFadeBlockDistance, uEndFadeBlockDistance, mcFragmentDistance);
fragColor = mix(combinedMcDhColor, dhColor, fadeStep);
fragColor.a = 1.0;
}
else
{
fragColor = vec4(combinedMcDhColor.rgb, 0.0);
}
}
@@ -0,0 +1,123 @@
#version 150
in vec4 vertexColor;
in vec3 vertexWorldPos;
in vec4 vPos;
in vec4 gl_FragCoord;
out vec4 fragColor;
// Fade/Clip Uniforms
uniform float uClipDistance = 0.0;
// Noise Uniforms
uniform bool uNoiseEnabled;
uniform int uNoiseSteps;
uniform float uNoiseIntensity;
uniform int uNoiseDropoff;
uniform bool uDitherDhRendering;
// The random functions for diffrent dimentions
float rand(float co) { return fract(sin(co*(91.3458)) * 47453.5453); }
float rand(vec2 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); }
float rand(vec3 co) { return rand(co.xy + rand(co.z)); }
// Puts steps in a float
// EG. setting stepSize to 4 then this would be the result of this function
// In: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, ..., 1.1, 1.2, 1.3
// Out: 0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, ..., 1.0, 1.0, 1.25
vec3 quantize(vec3 val, int stepSize)
{
return floor(val * stepSize) / stepSize;
}
void applyNoise(inout vec4 fragColor, const in float viewDist)
{
vec3 vertexNormal = normalize(cross(dFdy(vPos.xyz), dFdx(vPos.xyz)));
// This bit of code is required to fix the vertex position problem cus of floats in the verted world position varuable
vec3 fixedVPos = vPos.xyz + vertexNormal * 0.001;
float noiseAmplification = uNoiseIntensity;
float lum = (fragColor.r + fragColor.g + fragColor.b) / 3.0;
noiseAmplification = (1.0 - pow(lum * 2.0 - 1.0, 2.0)) * noiseAmplification; // Lessen the effect on depending on how dark the object is, equasion for this is -(2x-1)^{2}+1
noiseAmplification *= fragColor.a; // The effect would lessen on transparent objects
// Random value for each position
float randomValue = rand(quantize(fixedVPos, uNoiseSteps))
* 2.0 * noiseAmplification - noiseAmplification;
// Modifies the color
// A value of 0 on the randomValue will result in the original color, while a value of 1 will result in a fully bright color
vec3 newCol = fragColor.rgb + (1.0 - fragColor.rgb) * randomValue;
newCol = clamp(newCol, 0.0, 1.0);
if (uNoiseDropoff != 0) {
float distF = min(viewDist / uNoiseDropoff, 1.0);
newCol = mix(newCol, fragColor.rgb, distF); // The further away it gets, the less noise gets applied
}
fragColor.rgb = newCol;
}
/** returns a normalized value between 0.0 and 1.0 */
float bayerMatrix4x4(vec2 st)
{
int x = int(mod(st.x, 4.0));
int y = int(mod(st.y, 4.0));
// Flattened 4x4 Bayer matrix
float bayer4x4[16] = float[16](
0.0, 8.0, 2.0, 10.0,
12.0, 4.0, 14.0, 6.0,
3.0, 11.0, 1.0, 9.0,
15.0, 7.0, 13.0, 5.0
);
// Calculate the 1D index from the 2D coordinates
int index = y * 4 + x;
// Return the Bayer value normalized between 0.0 and 1.0
return bayer4x4[index] / 16.0;
}
void main()
{
fragColor = vertexColor;
float viewDist = length(vertexWorldPos);
if (uDitherDhRendering)
{
// Dither out the fragment based on distance and noise.
// Dithering is used since it works for both opaque and transparent rendering
// noise increases as the distance increases
// the fragCoord is used since it is stable and small so the dithering is cleaner
float worldNoise = bayerMatrix4x4(gl_FragCoord.xy);
// minor fudge factor to make sure all pixels fade out
// if not included 1 in 16 pixels would never fade away
worldNoise += 0.001;
float fadeStep = smoothstep(uClipDistance, uClipDistance * 1.5, viewDist);
if (fadeStep <= worldNoise)
{
discard;
}
}
else
{
if (viewDist < uClipDistance && uClipDistance > 0.0)
{
discard;
}
}
if (uNoiseEnabled)
{
applyNoise(fragColor, viewDist);
}
}
@@ -0,0 +1,27 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D uColorTexture;
uniform sampler2D uDepthTexture;
/**
* Fog application shader
*
* This merges the rendered fog onto DH's rendered LODs
*/
void main()
{
fragColor = vec4(0.0);
// a fragment depth of "1" means the fragment wasn't drawn to,
// only update fragments that were drawn to
float fragmentDepth = textureLod(uDepthTexture, TexCoord, 0).r;
if (fragmentDepth != 1)
{
fragColor = texture(uColorTexture, TexCoord);
}
}
@@ -0,0 +1,297 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D uDepthMap;
// inverted model view matrix and projection matrix
uniform mat4 uInvMvmProj;
// fog uniforms
uniform vec4 uFogColor;
uniform float uFogScale;
uniform float uFogVerticalScale;
uniform int uFogDebugMode;
uniform int uFogFalloffType;
// fog config
uniform float uFarFogStart;
uniform float uFarFogLength;
uniform float uFarFogMin;
uniform float uFarFogRange;
uniform float uFarFogDensity;
// height fog config
uniform float uHeightFogStart;
uniform float uHeightFogLength;
uniform float uHeightFogMin;
uniform float uHeightFogRange;
uniform float uHeightFogDensity;
uniform bool uHeightFogEnabled;
uniform int uHeightFogFalloffType;
uniform bool uHeightBasedOnCamera;
uniform float uHeightFogBaseHeight;
uniform bool uHeightFogAppliesUp;
uniform bool uHeightFogAppliesDown;
uniform bool uUseSphericalFog;
uniform int uHeightFogMixingMode;
uniform float uCameraBlockYPos;
//====================//
// method definitions //
//====================//
vec3 calcViewPosition(float fragmentDepth);
float getFarFogThickness(float dist);
float getHeightFogThickness(float dist);
float calculateHeightFogDepth(float worldYPos);
float mixFogThickness(float far, float height);
float linearFog(float worldDist, float fogStart, float fogLength, float fogMin, float fogRange);
float exponentialFog(float x, float fogStart, float fogLength, float fogMin, float fogRange, float fogDensity);
float exponentialSquaredFog(float x, float fogStart, float fogLength, float fogMin, float fogRange, float fogDensity);
//======//
// main //
//======//
/**
* Fragment shader for fog.
* This should be run last so it applies above other affects like Ambient Occlusioning
*/
void main()
{
float fragmentDepth = texture(uDepthMap, TexCoord).r;
fragColor = vec4(uFogColor.rgb, 0.0);
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to apply Fog to LODs, not to the sky outside the LODs
if (fragmentDepth < 1.0)
{
int fogDebugMode = uFogDebugMode;
if (fogDebugMode == 0)
{
// render fog based on distance from the camera
vec3 vertexWorldPos = calcViewPosition(fragmentDepth);
float horizontalWorldDistance = length(vertexWorldPos.xz) * uFogScale;
float worldDistance = length(vertexWorldPos.xyz) * uFogScale;
float activeDistance = uUseSphericalFog ? worldDistance : horizontalWorldDistance;
// far fog
float farFogThickness = getFarFogThickness(activeDistance);
// height fog
float heightFogDepth = calculateHeightFogDepth(vertexWorldPos.y);
float heightFogThickness = getHeightFogThickness(heightFogDepth);
// combined fog
float mixedFogThickness = mixFogThickness(farFogThickness, heightFogThickness);
fragColor.a = clamp(mixedFogThickness, 0.0, 1.0);
}
else if (fogDebugMode == 1)
{
// test code
// render everything with the fog color
fragColor.a = 1.0;
}
else
{
// test code.
// this can be fired by manually changing the fullFogMode to a (normally)
// invalid value (like 7).
// By having a separate if statement defined by
// a uniform we don't have to worry about GLSL optimizing away different
// options when testing, causing a bunch of headaches if we just want to render the screen red.
float depthValue = textureLod(uDepthMap, TexCoord, 0).r;
fragColor.rgb = vec3(depthValue); // Convert depth value to grayscale color
fragColor.a = 1.0;
}
}
}
//================//
// helper methods //
//================//
vec3 calcViewPosition(float fragmentDepth)
{
vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
ndc.xyz = ndc.xyz * 2.0 - 1.0;
vec4 eyeCoord = uInvMvmProj * ndc;
return eyeCoord.xyz / eyeCoord.w;
}
//=========//
// far fog //
//=========//
float getFarFogThickness(float dist)
{
if (uFogFalloffType == 0) // LINEAR
{
return linearFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange);
}
else if (uFogFalloffType == 1) // EXPONENTIAL
{
return exponentialFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange, uFarFogDensity);
}
else // EXPONENTIAL_SQUARED
{
return exponentialSquaredFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange, uFarFogDensity);
}
}
float getHeightFogThickness(float dist)
{
if (!uHeightFogEnabled)
{
return 0.0;
}
if (uHeightFogFalloffType == 0) // LINEAR
{
return linearFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange);
}
else if (uHeightFogFalloffType == 1) // EXPONENTIAL
{
return exponentialFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange, uHeightFogDensity);
}
else // EXPONENTIAL_SQUARED
{
return exponentialSquaredFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange, uHeightFogDensity);
}
}
float linearFog(float worldDist, float fogStart, float fogLength, float fogMin, float fogRange)
{
worldDist = (worldDist - fogStart) / fogLength;
worldDist = clamp(worldDist, 0.0, 1.0);
return fogMin + fogRange * worldDist;
}
float exponentialFog(
float x, float fogStart, float fogLength,
float fogMin, float fogRange, float fogDensity)
{
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
return fogMin + fogRange - fogRange/exp(x);
}
float exponentialSquaredFog(
float x, float fogStart, float fogLength,
float fogMin, float fogRange, float fogDensity)
{
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
return fogMin + fogRange - fogRange/exp(x*x);
}
//============//
// height fog //
//============//
/** 1 = full fog, 0 = no fog */
float calculateHeightFogDepth(float worldYPos)
{
// worldYPos -65 - 384
//worldYPos = worldYPos * -1; // negative, fog below height; positive, fog above height
//return worldYPos * uFogVerticalScale; // "* uFogVerticalScale" is done to convert world position to a percent of the world height;
if (!uHeightFogEnabled)
{
// ignore the height
return 0.0;
}
if (!uHeightBasedOnCamera)
{
worldYPos -= (uHeightFogBaseHeight - uCameraBlockYPos);
}
if (uHeightFogAppliesDown && uHeightFogAppliesUp)
{
return abs(worldYPos) * uFogVerticalScale;
}
else if (uHeightFogAppliesDown)
{
// apploy fog below given height
return -worldYPos * uFogVerticalScale;
}
else if (uHeightFogAppliesUp)
{
// apply fog above given height
return worldYPos * uFogVerticalScale;
}
else
{
// shouldn't happen,
return 0.0;
}
}
float mixFogThickness(float far, float height)
{
switch (uHeightFogMixingMode)
{
case 0: // BASIC
case 1: // IGNORE_HEIGHT
return far;
case 2: // MAX
return max(far, height);
case 3: // ADDITION
return (far + height);
case 4: // MULTIPLY
return far * height;
case 5: // INVERSE_MULTIPLY
return (1.0 - (1.0-far)*(1.0-height));
case 6: // LIMITED_ADDITION
return (far + max(far, height));
case 7: // MULTIPLY_ADDITION
return (far + far*height);
case 8: // INVERSE_MULTIPLY_ADDITION
return (far + 1.0 - (1.0-far)*(1.0-height));
case 9: // AVERAGE
return (far*0.5 + height*0.5);
}
// shouldn't happen, but default to BASIC / IGNORE_HEIGHT
// if an invalid option is selected
return far;
}
@@ -0,0 +1,10 @@
#version 150 core
in vec4 fColor;
out vec4 fragColor;
void main()
{
fragColor = fColor;
}
@@ -0,0 +1,41 @@
#version 150 core
uniform mat4 uTransform;
uniform vec4 uColor;
uniform int uSkyLight;
uniform int uBlockLight;
uniform sampler2D uLightMap;
uniform float uNorthShading;
uniform float uSouthShading;
uniform float uEastShading;
uniform float uWestShading;
uniform float uTopShading;
uniform float uBottomShading;
in vec3 vPosition;
out vec4 fColor;
void main()
{
gl_Position = uTransform * vec4(vPosition, 1.0);
float blockLight = (float(uBlockLight)+0.5) / 16.0;
float skyLight = (float(uSkyLight)+0.5) / 16.0;
vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0);
fColor = lightColor * uColor;
// apply directional shading
if (gl_VertexID >= 0 && gl_VertexID < 4) { fColor.rgb *= uNorthShading; }
else if (gl_VertexID >= 4 && gl_VertexID < 8) { fColor.rgb *= uSouthShading; }
else if (gl_VertexID >= 8 && gl_VertexID < 12) { fColor.rgb *= uWestShading; }
else if (gl_VertexID >= 12 && gl_VertexID < 16) { fColor.rgb *= uEastShading; }
else if (gl_VertexID >= 16 && gl_VertexID < 20) { fColor.rgb *= uBottomShading; }
else if (gl_VertexID >= 20 && gl_VertexID < 24) { fColor.rgb *= uTopShading; }
}
@@ -0,0 +1,10 @@
#version 150 core
in vec4 fColor;
out vec4 fragColor;
void main()
{
fragColor = fColor;
}
@@ -0,0 +1,66 @@
#version 330 core
layout (location = 1) in vec4 aColor;
layout (location = 2) in vec3 aScale;
layout (location = 3) in ivec3 aTranslateChunk;
layout (location = 4) in vec3 aTranslateSubChunk;
layout (location = 5) in int aMaterial;
uniform ivec3 uOffsetChunk;
uniform vec3 uOffsetSubChunk;
uniform ivec3 uCameraPosChunk;
uniform vec3 uCameraPosSubChunk;
uniform mat4 uProjectionMvm;
uniform int uSkyLight;
uniform int uBlockLight;
uniform sampler2D uLightMap;
uniform float uNorthShading;
uniform float uSouthShading;
uniform float uEastShading;
uniform float uWestShading;
uniform float uTopShading;
uniform float uBottomShading;
in vec3 vPosition;
out vec4 fColor;
void main()
{
// aTranslate - moves the vertex to the boxGroup's relative position
// uOffset - moves the vertex to the boxGroup's world position
// uCameraPos - moves the vertex into camera space
vec3 trans = (aTranslateChunk + uOffsetChunk - uCameraPosChunk) * 16.0f;
// separate float and int values are to fix percission loss at extreme distances from the origin (IE 10,000,000+)
// luckily large translate values minus large cameraPos generally equal values that cleanly fit in a float
trans += (aTranslateSubChunk + uOffsetSubChunk - uCameraPosSubChunk);
// combination translation and scaling matrix
mat4 transform = mat4(
aScale.x, 0.0, 0.0, 0.0,
0.0, aScale.y, 0.0, 0.0,
0.0, 0.0, aScale.z, 0.0,
trans.x, trans.y, trans.z, 1.0
);
gl_Position = uProjectionMvm * transform * vec4(vPosition, 1.0);
float blockLight = (float(uBlockLight)+0.5) / 16.0;
float skyLight = (float(uSkyLight)+0.5) / 16.0;
vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0);
fColor = lightColor * aColor;
// apply directional shading
if (gl_VertexID >= 0 && gl_VertexID < 4) { fColor.rgb *= uNorthShading; }
else if (gl_VertexID >= 4 && gl_VertexID < 8) { fColor.rgb *= uSouthShading; }
else if (gl_VertexID >= 8 && gl_VertexID < 12) { fColor.rgb *= uWestShading; }
else if (gl_VertexID >= 12 && gl_VertexID < 16) { fColor.rgb *= uEastShading; }
else if (gl_VertexID >= 16 && gl_VertexID < 20) { fColor.rgb *= uBottomShading; }
else if (gl_VertexID >= 20 && gl_VertexID < 24) { fColor.rgb *= uTopShading; }
}
@@ -0,0 +1,74 @@
#version 150 core
in vec4 vertexColor;
in vec4 vPos;
in vec3 vertexWorldPos;
out vec4 fragColor;
uniform float distanceScale;
uniform int uNoiseSteps;
uniform float uNoiseIntensity;
uniform float uNoiseDropoff;
// The random functions for diffrent dimentions
float rand(float co) { return fract(sin(co*(91.3458)) * 47453.5453); }
float rand(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); }
float rand(vec3 co){ return rand(co.xy+rand(co.z)); }
// Puts steps in a float
// EG. setting stepSize to 4 then this would be the result of this function
// In: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, ..., 1.1, 1.2, 1.3
// Out: 0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, ..., 1.0, 1.0, 1.25
float quantize(float val, int stepSize) {
return floor(val*stepSize)/stepSize;
}
vec3 quantize(vec3 val, int stepSize) {
return floor(val*stepSize)/stepSize;
}
/**
* Fragment shader for adding noise to lods.
* This should be passed close to first as it affects the base color of the lod
*
* version: 2023-6-21
*/
void main() {
// This bit of code is required to fix the vertex position problem cus of floats in the verted world position varuable
vec3 vertexNormal = normalize(cross(dFdx(vPos.xyz), dFdy(vPos.xyz)));
vec3 fixedVPos = vPos.xyz - vertexNormal * 0.001;
float noiseAmplification = uNoiseIntensity;
noiseAmplification = (-1 * pow(2*((vertexColor.x + vertexColor.y + vertexColor.z) / 3) - 1, 2) + 1) * noiseAmplification; // Lessen the effect on depending on how dark the object is, equasion for this is -(2x-1)^{2}+1
noiseAmplification *= vertexColor.w; // The effect would lessen on transparent objects
// Random value for each position
float randomValue = rand(quantize(fixedVPos.xyz, uNoiseSteps))
* 2.0 * noiseAmplification - noiseAmplification;
// Modifies the color
// A value of 0 on the randomValue will result in the original color, while a value of 1 will result in a fully bright color
vec3 newCol = (1.0 - vertexColor.rgb) * randomValue;
// Clamps it and turns it back into a vec4
float distA = length(vertexWorldPos) * distanceScale * uNoiseDropoff;
fragColor = clamp(vec4(newCol.rgb, distA), 0.0, 1.0); // The further away it gets, the less noise gets applied
// The further away it gets, the less noise gets applied
fragColor = vec4(0.0, 0.0, 0.0, randomValue);
// For testing
// if (vertexColor.r != 69420.) {
// fragColor = vec4(
// mod(fixedVPos.x, 1),
// mod(fixedVPos.y, 1),
// mod(fixedVPos.z, 1),
// 1f);
// }
}
@@ -0,0 +1,15 @@
#version 150 core
in vec2 vPosition;
out vec2 TexCoord;
/**
* This is specifically used by application shaders.
* IE post process or pixel transfer shaders, anything that is rendered using a single rectangle.
*/
void main()
{
gl_Position = vec4(vPosition, 1.0, 1.0);
TexCoord = vPosition.xy * 0.5 + 0.5;
}
@@ -0,0 +1,130 @@
#version 150 core
#extension GL_ARB_derivative_control : enable
#define SAMPLE_MAX 64
#define saturate(x) (clamp((x), 0.0, 1.0))
in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D uDepthMap;
uniform int uSampleCount;
uniform float uRadius;
uniform float uStrength;
uniform float uMinLight;
uniform float uBias;
uniform mat4 uInvProj;
uniform mat4 uProj;
uniform float uFadeDistanceInBlocks;
const float EPSILON = 1.e-6;
const float GOLDEN_ANGLE = 2.39996323;
const vec3 MAGIC = vec3(0.06711056, 0.00583715, 52.9829189);
const float PI = 3.1415926538;
const float TAU = PI * 2.0;
vec3 unproject(vec4 pos)
{
return pos.xyz / pos.w;
}
float InterleavedGradientNoise(const in vec2 pixel)
{
float x = dot(pixel, MAGIC.xy);
return fract(MAGIC.z * fract(x));
}
vec3 calcViewPosition(const in vec3 clipPos)
{
vec4 viewPos = uInvProj * vec4(clipPos * 2.0 - 1.0, 1.0);
return viewPos.xyz / viewPos.w;
}
float GetSpiralOcclusion(const in vec2 uv, const in vec3 viewPos, const in vec3 viewNormal)
{
float dither = InterleavedGradientNoise(gl_FragCoord.xy);
float rotatePhase = dither * TAU;
float rStep = uRadius / uSampleCount;
vec2 offset;
float ao = 0.0;
int sampleCount = 0;
float radius = rStep;
for (int i = 0; i < clamp(uSampleCount, 1, SAMPLE_MAX); i++) {
vec2 offset = vec2(
sin(rotatePhase),
cos(rotatePhase)
) * radius;
radius += rStep;
rotatePhase += GOLDEN_ANGLE;
vec3 sampleViewPos = viewPos + vec3(offset, -0.1);
vec3 sampleClipPos = unproject(uProj * vec4(sampleViewPos, 1.0)) * 0.5 + 0.5;
sampleClipPos = saturate(sampleClipPos);
float sampleClipDepth = textureLod(uDepthMap, sampleClipPos.xy, 0.0).r;
if (sampleClipDepth >= 1.0 - EPSILON) continue;
sampleClipPos.z = sampleClipDepth;
sampleViewPos = unproject(uInvProj * vec4(sampleClipPos * 2.0 - 1.0, 1.0));
vec3 diff = sampleViewPos - viewPos;
float sampleDist = length(diff);
vec3 sampleNormal = diff / sampleDist;
float sampleNoLm = max(dot(viewNormal, sampleNormal) - uBias, 0.0);
float aoF = 1.0 - saturate(sampleDist / uRadius);
ao += sampleNoLm * aoF;
sampleCount++;
}
ao /= max(sampleCount, 1);
ao = smoothstep(0.0, uStrength, ao);
return ao * (1.0 - uMinLight);
}
void main()
{
float fragmentDepth = textureLod(uDepthMap, TexCoord, 0).r;
float occlusion = 0.0;
// Do not apply to sky
if (fragmentDepth < 1.0)
{
vec3 viewPos = calcViewPosition(vec3(TexCoord, fragmentDepth));
// fading is done to prevent banding/noise
// at super far distance
float distanceFromCamera = length(viewPos);
float fadeDistance = uFadeDistanceInBlocks;
if (distanceFromCamera < fadeDistance)
{
#ifdef GL_ARB_derivative_control
// Get higher precision derivatives when available
vec3 viewNormal = cross(dFdxFine(viewPos.xyz), dFdyFine(viewPos.xyz));
#else
vec3 viewNormal = cross(dFdx(viewPos.xyz), dFdy(viewPos.xyz));
#endif
viewNormal = normalize(viewNormal);
occlusion = GetSpiralOcclusion(TexCoord, viewPos, viewNormal);
// linearly fade with distance
occlusion *= (fadeDistance - distanceFromCamera) / fadeDistance;
}
else
{
// we're out of range, no need to do any SSAO calculations
occlusion = 0.0;
}
}
fragColor = vec4(vec3(1.0 - occlusion), 1.0);
}
@@ -0,0 +1,78 @@
#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
uniform sampler2D gSSAOMap;
uniform sampler2D gDepthMap;
uniform vec2 gViewSize;
uniform int gBlurRadius;
uniform float gNear;
uniform float gFar;
float linearizeDepth(const in float depth) {
return (gNear * gFar) / (depth * (gNear - gFar) + gFar);
}
float Gaussian(const in float sigma, const in float x) {
return exp(-(x*x) / (2.0 * (sigma*sigma)));
}
float BilateralGaussianBlur(const in vec2 texcoord, const in float linearDepth, const in float g_sigmaV) {
float g_sigmaX = 1.6;
float g_sigmaY = 1.6;
int radius = clamp(gBlurRadius, 1, 3);
vec2 pixelSize = 1.0 / gViewSize;
float accum = 0.0;
float total = 0.0;
for (int iy = -radius; iy <= radius; iy++) {
float fy = Gaussian(g_sigmaY, iy);
for (int ix = -radius; ix <= radius; ix++) {
float fx = Gaussian(g_sigmaX, ix);
vec2 sampleTex = texcoord + ivec2(ix, iy) * pixelSize;
float sampleValue = textureLod(gSSAOMap, sampleTex, 0).r;
float sampleDepth = textureLod(gDepthMap, sampleTex, 0).r;
float sampleLinearDepth = linearizeDepth(sampleDepth);
float depthDiff = abs(sampleLinearDepth - linearDepth);
float fv = Gaussian(g_sigmaV, depthDiff);
float weight = fx*fy*fv;
accum += weight * sampleValue;
total += weight;
}
}
if (total <= 1.e-4) return 1.0;
return accum / total;
}
void main()
{
fragColor = vec4(1.0);
float fragmentDepth = textureLod(gDepthMap, TexCoord, 0).r;
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to apply SSAO to LODs, not to the sky outside the LODs
if (fragmentDepth < 1)
{
if (gBlurRadius > 0)
{
float fragmentDepthLinear = linearizeDepth(fragmentDepth);
fragColor.a = BilateralGaussianBlur(TexCoord, fragmentDepthLinear, 1.6);
}
else
{
fragColor.a = texelFetch(gSSAOMap, ivec2(gl_FragCoord.xy), 0).r;
}
}
}
@@ -0,0 +1,79 @@
#version 150 core
in uvec4 vPosition;
out vec4 vPos;
in vec4 color;
out vec4 vertexColor;
out vec3 vertexWorldPos;
out float vertexYPos;
uniform bool uIsWhiteWorld;
uniform mat4 uCombinedMatrix;
uniform vec3 uModelOffset;
uniform float uWorldYOffset;
uniform sampler2D uLightMap;
uniform float uMircoOffset;
uniform float uEarthRadius;
/**
* Vertex Shader
*
* author: James Seibel
* author: TomTheFurry
* author: stduhpf
* updated: coolGi
*
* version: 2025-12-22
*/
void main()
{
vPos = vPosition; // This is so it can be passed to the fragment shader
vertexWorldPos = vPosition.xyz + uModelOffset;
vertexYPos = vPosition.y + uWorldYOffset;
uint meta = vPosition.a;
uint mirco = (meta & 0xFF00u) >> 8u; // mirco offset which is a xyz 2bit value
// 0b00 = no offset
// 0b01 = positive offset
// 0b11 = negative offset
// format is: 0b00zzyyxx
float mx = (mirco & 1u)!=0u ? uMircoOffset : 0.0;
mx = (mirco & 2u)!=0u ? -mx : mx;
//float my = (mirco & 4u)!=0u ? uMircoOffset : 0.0;
//my = (mirco & 8u)!=0u ? -my : my;
float mz = (mirco & 16u)!=0u ? uMircoOffset : 0.0;
mz = (mirco & 32u)!=0u ? -mz : mz;
vertexWorldPos.x += mx;
//vertexWorldPos.y += my;
vertexWorldPos.z += mz;
// apply the earth curvature if needed
if (uEarthRadius < -1.0f || uEarthRadius > 1.0f)
{
// vertex transformation logic - stduhpf
float localRadius = uEarthRadius + vertexYPos;
float phi = length(vertexWorldPos.xz) / localRadius;
vertexWorldPos.y += (cos(phi) - 1.0) * localRadius;
vertexWorldPos.xz = vertexWorldPos.xz * sin(phi) / phi;
}
uint lights = meta & 0xFFu;
float skyLight = (float(lights/16u)+0.5) / 16.0;
float blockLight = (mod(float(lights), 16.0)+0.5) / 16.0;
vertexColor = vec4(texture(uLightMap, vec2(skyLight, blockLight)).xyz, 1.0);
if (!uIsWhiteWorld)
{
vertexColor *= color;
}
gl_Position = uCombinedMatrix * vec4(vertexWorldPos, 1.0);
}
@@ -0,0 +1,9 @@
#version 150 core
out vec4 fragColor;
// A test shader that makes everything darker
void main()
{
fragColor = vec4(0., 0., 1., 0.5);
}
@@ -0,0 +1,9 @@
#version 150 core
in vec4 fColor;
out vec4 fragColor;
void main()
{
fragColor = fColor;
}
@@ -0,0 +1,11 @@
#version 150 core
in vec2 vPosition;
in vec4 color;
out vec4 fColor;
void main()
{
gl_Position = vec4(vPosition, 0.0, 1.0);
fColor = color;
}
@@ -0,0 +1,37 @@
CREATE TABLE DhFullData(
DhSectionPos TEXT NOT NULL PRIMARY KEY
-- meta data
,DataDetailLevel TINYINT NULL
,Checksum INT NULL
,DataVersion BIGINT NULL
,WorldGenStep NVARCHAR(32) NULL
,DataType NVARCHAR(48) NULL
,BinaryDataFormatVersion TINYINT NULL
,Data BLOB NULL
,CreatedDateTime DATETIME NOT NULL default CURRENT_TIMESTAMP -- in UTC
,LastModifiedDateTime DATETIME NOT NULL default CURRENT_TIMESTAMP -- in UTC
);
-- Note: each statement must be separated by the following batch comment line otherwise Java won't run anything after the first query
--batch--
CREATE TABLE DhRenderData(
DhSectionPos TEXT NOT NULL PRIMARY KEY
-- meta data
,DataDetailLevel TINYINT NULL
,Checksum INT NULL
,DataVersion BIGINT NULL
,WorldGenStep NVARCHAR(32) NULL
,DataType NVARCHAR(48) NULL
,BinaryDataFormatVersion TINYINT NULL
,Data BLOB NULL
,CreatedDateTime DATETIME NOT NULL default CURRENT_TIMESTAMP -- in UTC
,LastModifiedDateTime DATETIME NOT NULL default CURRENT_TIMESTAMP -- in UTC
);
@@ -0,0 +1,33 @@
ALTER TABLE DhFullData RENAME TO Legacy_FullData_V1;
--batch--
ALTER TABLE Legacy_FullData_V1 ADD COLUMN MigrationFailed BIT NOT NULL DEFAULT 0;
--batch--
CREATE TABLE FullData (
-- compound primary key
DetailLevel TINYINT NOT NULL -- LOD detail level, not section detail level IE 0, 1, 2 not 6, 7, 8
,PosX INT NOT NULL
,PosZ INT NOT NULL
,MinY INT NOT NULL
,DataChecksum INT NOT NULL
,Data BLOB NULL
,ColumnGenerationStep BLOB NULL
,ColumnWorldCompressionMode BLOB NULL
,Mapping BLOB NULL
,DataFormatVersion TINYINT NULL
,CompressionMode TINYINT NULL
,ApplyToParent BIT NULL
,LastModifiedUnixDateTime BIGINT NOT NULL -- in GMT 0
,CreatedUnixDateTime BIGINT NOT NULL -- in GMT 0
,PRIMARY KEY (DetailLevel, PosX, PosZ)
);
@@ -0,0 +1,9 @@
-- this PRAGMA will automatically commit, so we have to disable
-- DH's automatic transactions, otherwise the connection will throw an error
--No Transactions--
-- James ran into some issues where Windows had trouble deleting the Journal file,
-- using TRUNCATE should fix that issue
PRAGMA journal_mode = TRUNCATE;
@@ -0,0 +1,8 @@
-- these PRAGMA's will automatically commit, so we have to disable
-- DH's automatic transactions, otherwise the connection will throw an error
--No Transactions--
pragma journal_mode = WAL;
pragma synchronous = NORMAL;
@@ -0,0 +1,4 @@
-- The render cache was discovered to not speed up LOD loading,
-- so to reduce DB file size it was removed.
drop table DhRenderData;
@@ -0,0 +1,3 @@
-- significantly speeds up parent update handling
create index FullDataUpdatedIndex on FullData (ApplyToParent) where ApplyToParent = 1
@@ -0,0 +1,13 @@
CREATE TABLE ChunkHash(
-- compound primary key
ChunkPosX INT NOT NULL
,ChunkPosZ INT NOT NULL
,ChunkHash INT NOT NULL
,LastModifiedUnixDateTime BIGINT NOT NULL -- in GMT 0
,CreatedUnixDateTime BIGINT NOT NULL -- in GMT 0
,PRIMARY KEY (ChunkPosX, ChunkPosZ)
);
@@ -0,0 +1,16 @@
CREATE TABLE BeaconBeam(
-- compound primary key
BlockPosX INT NOT NULL
,BlockPosY INT NOT NULL
,BlockPosZ INT NOT NULL
,ColorR INT NOT NULL
,ColorG INT NOT NULL
,ColorB INT NOT NULL
,LastModifiedUnixDateTime BIGINT NOT NULL -- in GMT 0
,CreatedUnixDateTime BIGINT NOT NULL -- in GMT 0
,PRIMARY KEY (BlockPosX, BlockPosY, BlockPosZ)
);
@@ -0,0 +1,9 @@
-- Applying to children is needed to fix a bug with N-sized generation.
-- If we don't fill the whole tree with data, it's possible to render empty/incomplete LODs, which looks bad.
alter table FullData add column ApplyToChildren BIT NULL;
--batch--
-- significantly speeds up update handling
create index FullDataApplyToChildrenIndex on FullData (ApplyToChildren) where ApplyToChildren = 1;
@@ -0,0 +1,12 @@
-- storing adjacent data (IE a single line of data on the +X/-X/+Z/-Z axis)
-- allows for significantly reduced render loading times since we only have to
-- handle part of the adjacent data source vs all of it
alter table FullData add column NorthAdjData BLOB NULL;
--batch--
alter table FullData add column SouthAdjData BLOB NULL;
--batch--
alter table FullData add column EastAdjData BLOB NULL;
--batch--
alter table FullData add column WestAdjData BLOB NULL;
@@ -0,0 +1,13 @@
-- This is done to fix a bug where a lot of unnecessary
-- ID mapping data is saved, which significantly reduces
-- loading/deserializing/decompression time
-- delete all data above 0 (max detail)
-- so it can be re-created
delete from FullData where DetailLevel > 0;
--batch--
-- re-downsample all LOD data
update FullData set ApplyToParent = 1;
@@ -0,0 +1,51 @@
### All Sql scripts should be run exactly once per database and old scripts shouldn't be changed. Any necessary schema changes should be done by creating new scripts that modify the existing database.
This system is roughly based on the DbUp library from .NET, for information about DbUp and it's general philosophy please refer to the following doc:
https://dbup.readthedocs.io/en/latest/philosophy-behind-dbup/
<br>
### Adding New Scripts:
New scripts must be added to the "scriptList.txt" file, otherwise they will not be run. <br>
(If anyone has a good way to automatically pull all resource files ending in `.sql` instead, please let us know.)
<br>
### File Naming:
- The first 3 numbers are major scripts.
- The 4th number is for minor/related scripts or if a bug fix needs to be applied between scripts.
- flavor of database the script is for (for now this is just sqlite)
- description of the script
<br>
### Mutli-query Scripts:
When creating a script with multiple queries the queries must be separated with the SQL comment `--batch--` otherwise only the first query will be executed.
Example:
```roomsql
CREATE TABLE TableOne(
DhSectionPos TEXT NOT NULL PRIMARY KEY
,Data BLOB NULL
);
--batch--
CREATE TABLE TableTwo(
DhSectionPos TEXT NOT NULL PRIMARY KEY
,Data BLOB NULL
);
```
### PRAGMA Auto Commits
Certain queries will auto commit after running, specifically certain `PRAGMA` commands. In that case we have to disable DH's automatic transactions by putting `--No Transactions--` somewhere in the file. Otherwise, when the system attempts to commit, it will fail due to the PRAGMA having already committed itself.
Due to how these commands work it's best to only have a single command in the file to prevent confusion and potential database corruption.
```roomsql
--No Transactions--
PRAGMA journal_mode = TRUNCATE;
```
@@ -0,0 +1,12 @@
0010-sqlite-createInitialDataTables.sql
0020-sqlite-createFullDataSourceV2Tables.sql
0030-sqlite-changeTableJournaling.sql
0031-sqlite-useSqliteWalJournaling.sql
0040-sqlite-removeRenderCache.sql
0050-sqlite-addApplyToParentIndex.sql
0060-sqlite-createChunkHashTable.sql
0070-sqlite-createBeaconBeamTable.sql
0080-sqlite-addApplyToChildrenColumn.sql
0090-sqlite-addAdjacentFullDataColumns.sql
0100-sqlite-deleteLowDetailDataForRegen.sql