From 32c63ae15bd5d34c8fbf70895afdfebf834ac751 Mon Sep 17 00:00:00 2001 From: s809 <11816467-s809@users.noreply.gitlab.com> Date: Sun, 28 Jul 2024 17:06:36 +0500 Subject: [PATCH] Reapply "Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons into serverside" This reverts commit a2d5e8cdb31dd2aeb3ebd5b52155e8fb38c10ece. --- .../common/wrappers/McObjectConverter.java | 2 +- .../common/wrappers/WrapperFactory.java | 35 ++- .../wrappers/block/BlockStateWrapper.java | 206 ++++++++++++++---- .../common/wrappers/chunk/ChunkWrapper.java | 15 +- .../common/wrappers/gui/ClassicConfigGUI.java | 19 +- .../wrappers/gui/updater/ChangelogScreen.java | 12 +- .../minecraft/MinecraftClientWrapper.java | 120 +++++----- .../minecraft/MinecraftRenderWrapper.java | 13 +- .../common/wrappers/misc/LightMapWrapper.java | 21 +- .../wrappers/misc/ServerPlayerWrapper.java | 2 +- .../wrappers/world/ClientLevelWrapper.java | 47 +++- .../wrappers/world/ServerLevelWrapper.java | 54 ++--- .../BatchGenerationEnvironment.java | 26 ++- .../mimicObject/ChunkLoader.java | 16 +- .../worldGeneration/step/StepBiomes.java | 7 +- .../worldGeneration/step/StepFeatures.java | 8 +- .../step/StepStructureReference.java | 7 +- .../step/StepStructureStart.java | 13 +- .../worldGeneration/step/StepSurface.java | 7 +- .../fabric/FabricClientProxy.java | 73 ++++--- .../mixins/client/MixinLevelRenderer.java | 16 +- .../wrappers/modAccessor/SodiumAccessor.java | 2 +- .../forge/ForgeClientProxy.java | 25 ++- .../mixins/client/MixinLevelRenderer.java | 11 +- gradle.properties | 2 +- .../neoforge/NeoforgeClientProxy.java | 46 ++-- .../mixins/client/MixinLevelRenderer.java | 2 +- wipelod.ps1 | 4 + 28 files changed, 536 insertions(+), 275 deletions(-) create mode 100644 wipelod.ps1 diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java index ebcab8af8..e475dbc69 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/McObjectConverter.java @@ -26,7 +26,7 @@ import java.util.function.Consumer; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java index 2d5ded61e..39f121341 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java @@ -55,9 +55,6 @@ import java.util.HashSet; /** * This handles creating abstract wrapper objects. - * - * @author James Seibel - * @version 2022-12-5 */ public class WrapperFactory implements IWrapperFactory { @@ -82,6 +79,27 @@ public class WrapperFactory implements IWrapperFactory } } + @Override + public IDhApiBiomeWrapper getBiomeWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException + { + if (!(levelWrapper instanceof ILevelWrapper)) + { + throw new ClassCastException("levelWrapper must be returned by DH and of type ["+ILevelWrapper.class.getName()+"]."); + } + + return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); + } + @Override + public IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException + { + if (!(levelWrapper instanceof ILevelWrapper)) + { + throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"]."); + } + + return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); + } + @Override public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); } @Override @@ -104,6 +122,13 @@ public class WrapperFactory implements IWrapperFactory @Override public HashSet getRendererIgnoredBlocks(ILevelWrapper levelWrapper) { return BlockStateWrapper.getRendererIgnoredBlocks(levelWrapper); } + @Override + public HashSet getRendererIgnoredCaveBlocks(ILevelWrapper levelWrapper) { return BlockStateWrapper.getRendererIgnoredCaveBlocks(levelWrapper); } + + @Override + public void resetRendererIgnoredCaveBlocks() { BlockStateWrapper.clearRendererIgnoredCaveBlocks(); } + @Override + public void resetRendererIgnoredBlocksSet() { BlockStateWrapper.clearRendererIgnoredBlocks(); } /** @@ -212,7 +237,7 @@ public class WrapperFactory implements IWrapperFactory // confirm the API level wrapper is also a Core wrapper if (!(levelWrapper instanceof ILevelWrapper)) { - throw new ClassCastException("Unable to cast... only DH provided IDhApiLevelWrapper's can be used."); // TODO + throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"]."); } ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper; @@ -271,7 +296,7 @@ public class WrapperFactory implements IWrapperFactory // confirm the API level wrapper is also a Core wrapper if (!(levelWrapper instanceof ILevelWrapper)) { - throw new ClassCastException("Unable to cast... only DH provided IDhApiLevelWrapper's can be used."); // TODO + throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"]."); } ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper; diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java index 528bd11f7..d3e3061e0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java @@ -19,7 +19,12 @@ package com.seibel.distanthorizons.common.wrappers.block; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.config.types.ConfigEntry; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.ColorUtil; +import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; @@ -31,8 +36,10 @@ import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; import org.apache.logging.log4j.Logger; +import java.awt.*; import java.io.IOException; import java.util.*; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 @@ -71,9 +78,8 @@ public class BlockStateWrapper implements IBlockStateWrapper public static final String DIRT_RESOURCE_LOCATION_STRING = "minecraft:dirt"; - // TODO: Make this changeable through the config - public static final String[] RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS = { AIR_STRING, "minecraft:barrier", "minecraft:structure_void", "minecraft:light", "minecraft:tripwire" }; public static HashSet rendererIgnoredBlocks = null; + public static HashSet rendererIgnoredCaveBlocks = null; /** keep track of broken blocks so we don't log every time */ private static final HashSet BrokenResourceLocations = new HashSet<>(); @@ -88,11 +94,16 @@ public class BlockStateWrapper implements IBlockStateWrapper private final int hashCode; /** * Cached opacity value, -1 if not populated.
- * Should be between {@link IBlockStateWrapper#FULLY_OPAQUE} and {@link IBlockStateWrapper#FULLY_OPAQUE} + * Should be between {@link LodUtil#BLOCK_FULLY_OPAQUE} and {@link LodUtil#BLOCK_FULLY_OPAQUE} */ private int opacity = -1; /** used by the Iris shader mod to determine how each LOD should be rendered */ - private byte irisBlockMaterialId = 0; + private byte blockMaterialId = 0; + + private final boolean isBeaconBlock; + private final boolean isBeaconBaseBlock; + private final boolean isGlassBlock; + private final Color mapColor; @@ -125,16 +136,46 @@ public class BlockStateWrapper implements IBlockStateWrapper this.blockState = blockState; this.serialString = this.serialize(levelWrapper); this.hashCode = Objects.hash(this.serialString); - this.irisBlockMaterialId = this.calculateIrisBlockMaterialId(); + this.blockMaterialId = this.calculateEDhApiBlockMaterialId().index; - //LOGGER.trace("Created BlockStateWrapper ["+this.serialString+"] for ["+blockState+"] with material ID ["+this.irisBlockMaterialId+"]"); + String lowercaseSerial = this.serialString.toLowerCase(); + boolean isBeaconBaseBlock = false; + for (int i = 0; i < LodUtil.BEACON_BASE_BLOCK_NAME_LIST.size(); i++) + { + String baseBlockName = LodUtil.BEACON_BASE_BLOCK_NAME_LIST.get(i); + if (lowercaseSerial.contains(baseBlockName)) + { + isBeaconBaseBlock = true; + break; + } + } + this.isBeaconBaseBlock = isBeaconBaseBlock; + this.isBeaconBlock = lowercaseSerial.contains("minecraft:beacon"); + this.isGlassBlock = lowercaseSerial.contains("glass"); + + int mcColor = 0; + if (this.blockState != null) + { + #if MC_VER < MC_1_20_1 + mcColor = this.blockState.getMaterial().getColor().col; + #else + mcColor = this.blockState.getMapColor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).col; + #endif + this.mapColor = ColorUtil.toColorObjRGB(mcColor); + } + else + { + this.mapColor = new Color(0,0,0,0); + } + + //LOGGER.trace("Created BlockStateWrapper ["+this.serialString+"] for ["+blockState+"] with material ID ["+this.EDhApiBlockMaterialId+"]"); } - //================// - // helper methods // - //================// + //====================// + // LodBuilder methods // + //====================// /** * Requires a {@link ILevelWrapper} since {@link BlockStateWrapper#deserialize(String,ILevelWrapper)} also requires one. @@ -148,37 +189,104 @@ public class BlockStateWrapper implements IBlockStateWrapper return rendererIgnoredBlocks; } + HashSet baseIgnoredBlock = new HashSet<>(); + baseIgnoredBlock.add(AIR_STRING); + rendererIgnoredBlocks = getBlockWrappers(Config.Client.Advanced.LodBuilding.ignoredRenderBlockCsv, baseIgnoredBlock, levelWrapper); + return rendererIgnoredBlocks; + } + /** + * Requires a {@link ILevelWrapper} since {@link BlockStateWrapper#deserialize(String,ILevelWrapper)} also requires one. + * This way the method won't accidentally be called before the deserialization can be completed. + */ + public static HashSet getRendererIgnoredCaveBlocks(ILevelWrapper levelWrapper) + { + // use the cached version if possible + if (rendererIgnoredCaveBlocks != null) + { + return rendererIgnoredCaveBlocks; + } + HashSet baseIgnoredBlock = new HashSet<>(); + baseIgnoredBlock.add(AIR_STRING); + rendererIgnoredCaveBlocks = getBlockWrappers(Config.Client.Advanced.LodBuilding.ignoredRenderCaveBlockCsv, baseIgnoredBlock, levelWrapper); + return rendererIgnoredCaveBlocks; + } + + public static void clearRendererIgnoredBlocks() { rendererIgnoredBlocks = null; } + public static void clearRendererIgnoredCaveBlocks() { rendererIgnoredCaveBlocks = null; } + + + + // lod builder helpers // + + private static HashSet getBlockWrappers(ConfigEntry config, HashSet baseResourceLocations, ILevelWrapper levelWrapper) + { + // get the base blocks + HashSet blockStringList = new HashSet<>(); + if (baseResourceLocations != null) + { + blockStringList.addAll(baseResourceLocations); + } + + // get the config blocks + String ignoreBlockCsv = config.get(); + if (ignoreBlockCsv != null) + { + blockStringList.addAll(List.of(ignoreBlockCsv.split(","))); + } + + return getBlockWrappers(blockStringList, levelWrapper); + } + private static HashSet getBlockWrappers(HashSet blockResourceLocationSet, ILevelWrapper levelWrapper) + { // deserialize each of the given resource locations HashSet blockStateWrappers = new HashSet<>(); - for (String blockResourceLocation : RENDERER_IGNORED_BLOCKS_RESOURCE_LOCATIONS) + for (String blockResourceLocation : blockResourceLocationSet) { try { - BlockStateWrapper DefaultBlockStateToIgnore = (BlockStateWrapper) deserialize(blockResourceLocation, levelWrapper); - blockStateWrappers.add(DefaultBlockStateToIgnore); - - if (DefaultBlockStateToIgnore == AIR) + if (blockResourceLocation == null) + { + // shouldn't happen, but just in case + continue; + } + String cleanedResourceLocation = blockResourceLocation.trim(); + if (cleanedResourceLocation.length() == 0) { continue; } - // add all possible blockstates (to account for light blocks with different light values and such) - List blockStatesToIgnore = DefaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates(); - for (BlockState blockState : blockStatesToIgnore) + + BlockStateWrapper defaultBlockStateToIgnore = (BlockStateWrapper) deserialize(cleanedResourceLocation, levelWrapper); + blockStateWrappers.add(defaultBlockStateToIgnore); + + if (defaultBlockStateToIgnore != AIR) { - BlockStateWrapper newBlockToIgnore = BlockStateWrapper.fromBlockState(blockState, levelWrapper); - blockStateWrappers.add(newBlockToIgnore); + // add all possible blockstates (to account for light blocks with different light values and such) + List blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates(); + for (BlockState blockState : blockStatesToIgnore) + { + BlockStateWrapper newBlockToIgnore = BlockStateWrapper.fromBlockState(blockState, levelWrapper); + blockStateWrappers.add(newBlockToIgnore); + } + } + else + { + // air is a special case so it must be handled separately + blockStateWrappers.add(AIR); } } catch (IOException e) { - LOGGER.warn("Unable to deserialize rendererIgnoredBlock with the resource location: ["+blockResourceLocation+"]. Error: "+e.getMessage(), e); + LOGGER.warn("Unable to deserialize block with the resource location: ["+blockResourceLocation+"]. Error: "+e.getMessage(), e); + } + catch (Exception e) + { + LOGGER.warn("Unexpected error deserializing block with the resource location: ["+blockResourceLocation+"]. Error: "+e.getMessage(), e); } } - rendererIgnoredBlocks = blockStateWrappers; - return rendererIgnoredBlocks; + return blockStateWrappers; } @@ -201,23 +309,23 @@ public class BlockStateWrapper implements IBlockStateWrapper int opacity; if (this.isAir()) { - opacity = FULLY_TRANSPARENT; + opacity = LodUtil.BLOCK_FULLY_TRANSPARENT; } else if (this.isLiquid() && !this.blockState.canOcclude()) { // probably not a waterlogged block (which should block light entirely) // +1 to indicate that the block is translucent (in between transparent and opaque) - opacity = FULLY_TRANSPARENT + 1; + opacity = LodUtil.BLOCK_FULLY_TRANSPARENT + 1; } else if (this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) { - opacity = FULLY_TRANSPARENT; + opacity = LodUtil.BLOCK_FULLY_TRANSPARENT; } else { // default for all other blocks - opacity = FULLY_OPAQUE; + opacity = LodUtil.BLOCK_FULLY_OPAQUE; } @@ -286,7 +394,17 @@ public class BlockStateWrapper implements IBlockStateWrapper } @Override - public byte getIrisBlockMaterialId() { return this.irisBlockMaterialId; } + public boolean isBeaconBlock() { return this.isBeaconBlock; } + @Override + public boolean isBeaconBaseBlock() { return this.isBeaconBaseBlock; } + @Override + public boolean isGlassBlock() { return this.isGlassBlock; } + + @Override + public Color getMapColor() { return this.mapColor; } + + @Override + public byte getMaterialId() { return this.blockMaterialId; } @Override public String toString() { return this.getSerialString(); } @@ -509,11 +627,11 @@ public class BlockStateWrapper implements IBlockStateWrapper // Iris methods // //==============// - private byte calculateIrisBlockMaterialId() + private EDhApiBlockMaterial calculateEDhApiBlockMaterialId() { if (this.blockState == null) { - return IrisBlockMaterial.AIR; + return EDhApiBlockMaterial.AIR; } @@ -526,15 +644,15 @@ public class BlockStateWrapper implements IBlockStateWrapper || serialString.contains("mushroom") ) { - return IrisBlockMaterial.LEAVES; + return EDhApiBlockMaterial.LEAVES; } else if (this.blockState.is(Blocks.LAVA)) { - return IrisBlockMaterial.LAVA; + return EDhApiBlockMaterial.LAVA; } else if (this.isLiquid() || this.blockState.is(Blocks.WATER)) { - return IrisBlockMaterial.WATER; + return EDhApiBlockMaterial.WATER; } else if (this.blockState.getSoundType() == SoundType.WOOD || serialString.contains("root") @@ -543,7 +661,7 @@ public class BlockStateWrapper implements IBlockStateWrapper #endif ) { - return IrisBlockMaterial.WOOD; + return EDhApiBlockMaterial.WOOD; } else if (this.blockState.getSoundType() == SoundType.METAL #if MC_VER >= MC_1_19_2 @@ -555,11 +673,11 @@ public class BlockStateWrapper implements IBlockStateWrapper #endif ) { - return IrisBlockMaterial.METAL; + return EDhApiBlockMaterial.METAL; } else if (serialString.contains("grass_block")) { - return IrisBlockMaterial.GRASS; + return EDhApiBlockMaterial.GRASS; } else if ( serialString.contains("dirt") @@ -569,7 +687,7 @@ public class BlockStateWrapper implements IBlockStateWrapper || serialString.contains("mycelium") ) { - return IrisBlockMaterial.DIRT; + return EDhApiBlockMaterial.DIRT; } #if MC_VER >= MC_1_17_1 else if (this.blockState.getSoundType() == SoundType.DEEPSLATE @@ -578,37 +696,37 @@ public class BlockStateWrapper implements IBlockStateWrapper || this.blockState.getSoundType() == SoundType.POLISHED_DEEPSLATE || serialString.contains("deepslate") ) { - return IrisBlockMaterial.DEEPSLATE; + return EDhApiBlockMaterial.DEEPSLATE; } #endif else if (this.serialString.contains("snow")) { - return IrisBlockMaterial.SNOW; + return EDhApiBlockMaterial.SNOW; } else if (serialString.contains("sand")) { - return IrisBlockMaterial.SAND; + return EDhApiBlockMaterial.SAND; } else if (serialString.contains("terracotta")) { - return IrisBlockMaterial.TERRACOTTA; + return EDhApiBlockMaterial.TERRACOTTA; } else if (this.blockState.is(BlockTags.BASE_STONE_NETHER)) { - return IrisBlockMaterial.NETHER_STONE; + return EDhApiBlockMaterial.NETHER_STONE; } else if (serialString.contains("stone") || serialString.contains("ore")) { - return IrisBlockMaterial.STONE; + return EDhApiBlockMaterial.STONE; } else if (this.blockState.getLightEmission() > 0) { - return IrisBlockMaterial.ILLUMINATED; + return EDhApiBlockMaterial.ILLUMINATED; } else { - return IrisBlockMaterial.UNKOWN; + return EDhApiBlockMaterial.UNKNOWN; } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java index 144949d0a..51101f7b5 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/chunk/ChunkWrapper.java @@ -227,6 +227,9 @@ public class ChunkWrapper implements IChunkWrapper LevelChunkSection[] sections = this.chunk.getSections(); for (int index = sections.length-1; index >= 0; index--) { + // update at each position to fix using the max height if the chunk is empty + this.maxNonEmptyHeight = this.getChunkSectionMinHeight(index) + 16; + if (sections[index] == null) { continue; @@ -234,7 +237,7 @@ public class ChunkWrapper implements IChunkWrapper if (!isChunkSectionEmpty(sections[index])) { - this.maxNonEmptyHeight = this.getChunkSectionMinHeight(index) + 16; + // non-empty section found break; } } @@ -251,15 +254,7 @@ public class ChunkWrapper implements IChunkWrapper return section.hasOnlyAir(); #endif } - private int getChunkSectionMinHeight(int index) - { - // convert from an index to a block coordinate - #if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 - return this.chunk.getSections()[index].bottomBlockY(); - #else - return this.chunk.getSectionYFromSectionIndex(index) * 16; - #endif - } + private int getChunkSectionMinHeight(int index) { return (index * 16) + this.getMinBuildHeight(); } @Override diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java index ffb8d9412..2ca6c27a0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/ClassicConfigGUI.java @@ -158,19 +158,22 @@ public class ClassicConfigGUI // button.active = entries.stream().allMatch(e -> e.inLimits); - if (((ConfigEntry) info).isValid(value) == 0 && info.getType() != List.class) + if (info.getType() == String.class + || info.getType() == List.class) + { + ((ConfigEntry) info).uiSetWithoutSaving(stringValue); + } + else if (((ConfigEntry) info).isValid(value) == 0) { if (!cast) + { ((ConfigEntry) info).uiSetWithoutSaving(value); + } else + { ((ConfigEntry) info).uiSetWithoutSaving(value.intValue()); + } } -// else if (((ConfigEntry) info).isValidMemoryAddress() == 0) -// { -// if (((List) info.get()).size() == ((EntryInfo) info.guiValue).index) -// info.uiSet(((List) info.get()).add("")); -// info.uiSet(((List) info.get()).set(((EntryInfo) info.guiValue).index, Arrays.stream(((EntryInfo) info.guiValue).tempValue.replace("[", "").replace("]", "").split(", ")).collect(Collectors.toList()).get(0))); -// } return true; }; @@ -443,7 +446,9 @@ public class ClassicConfigGUI String key = translationPrefix + (newInfo.category.isEmpty() ? "" : newInfo.category + ".") + newInfo.getName() + ".@tooltip"; if (((EntryInfo) newInfo.guiValue).error != null && text.equals(name)) + { DhRenderTooltip(matrices, font, ((EntryInfo) newInfo.guiValue).error.getValue(), mouseX, mouseY); + } else if (I18n.exists(key) && (text != null && text.equals(name))) { List list = new ArrayList<>(); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java index 76adb6d58..25ac35ea3 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/gui/updater/ChangelogScreen.java @@ -101,11 +101,17 @@ public class ChangelogScreen extends DhScreen this.changelog.add(""); this.changelog.add(""); + String changelog = ModrinthGetter.changeLogs.get(versionID); + if (changelog == null) + { + // in case something goes wrong this will prevent null pointers + changelog = ""; + } + // Get the release changelog and split it by the new lines String[] unwrappedChangelog = // Arrays.asList could be used if a list object is desired here vs List.of which is only available for Java 9+ - new MarkdownFormatter.MinecraftFormat().convertTo( // This formats markdown to minecraft's "§" characters - ModrinthGetter.changeLogs.get(versionID) - ).split("\\n"); + // This formats markdown to minecraft's "§" charactersnew MarkdownFormatter.MinecraftFormat().convertTo( + new MarkdownFormatter.MinecraftFormat().convertTo(changelog).split("\\n"); // Makes the words wrap around to not go off the screen for (String str : unwrappedChangelog) { diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java index 81772d44e..7adb86b9f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java @@ -31,6 +31,7 @@ import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.enums.EDhDirection; +import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -44,6 +45,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos; import net.minecraft.CrashReport; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.core.BlockPos; @@ -60,16 +62,15 @@ import org.jetbrains.annotations.Nullable; * A singleton that wraps the Minecraft object. * * @author James Seibel - * @version 3-5-2022 */ -//@Environment(EnvType.CLIENT) public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper { private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); + private static final Minecraft MINECRAFT = Minecraft.getInstance(); public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper(); - public final Minecraft mc = Minecraft.getInstance(); + /** * The lightmap for the current: @@ -100,10 +101,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra * This doesn't affect OpenGL objects in any way. */ @Override - public void clearFrameObjectCache() - { - this.lightMap = null; - } + public void clearFrameObjectCache() { this.lightMap = null; } @@ -119,10 +117,10 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra { default: case AUTO: - if (this.mc.level != null) + if (MINECRAFT.level != null) { Direction mcDir = McObjectConverter.Convert(lodDirection); - return this.mc.level.getShade(mcDir, true); + return MINECRAFT.level.getShade(mcDir, true); } else { @@ -151,42 +149,58 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra } @Override - public boolean hasSinglePlayerServer() { return this.mc.hasSingleplayerServer(); } + public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); } @Override - public boolean clientConnectedToDedicatedServer() { return this.mc.getCurrentServer() != null && !this.hasSinglePlayerServer(); } + public boolean clientConnectedToDedicatedServer() { return MINECRAFT.getCurrentServer() != null && !this.hasSinglePlayerServer(); } + @Override + public boolean connectedToReplay() { return !MINECRAFT.hasSingleplayerServer() && MINECRAFT.getCurrentServer() == null; } @Override - public String getCurrentServerName() { return this.mc.getCurrentServer().name; } + public String getCurrentServerName() + { + if (this.connectedToReplay()) + { + return ClientOnlySaveStructure.REPLAY_SERVER_FOLDER_NAME; + } + else + { + ServerData server = MINECRAFT.getCurrentServer(); + return (server != null) ? server.name : "NULL"; + } + } @Override - public String getCurrentServerIp() { return this.mc.getCurrentServer().ip; } + public String getCurrentServerIp() + { + if (this.connectedToReplay()) + { + return ""; + } + else + { + ServerData server = MINECRAFT.getCurrentServer(); + return (server != null) ? server.ip : "NA"; + } + } @Override public String getCurrentServerVersion() { - return this.mc.getCurrentServer().version.getString(); + ServerData server = MINECRAFT.getCurrentServer(); + return (server != null) ? server.version.getString() : "UNKOWN"; } //=============// // Simple gets // //=============// - public LocalPlayer getPlayer() - { - return this.mc.player; - } + public LocalPlayer getPlayer() { return MINECRAFT.player; } @Override - public boolean playerExists() - { - return this.mc.player != null; - } + public boolean playerExists() { return MINECRAFT.player != null; } @Override - public UUID getPlayerUUID() - { - return this.getPlayer().getUUID(); - } + public UUID getPlayerUUID() { return this.getPlayer().getUUID(); } @Override public DhBlockPos getPlayerBlockPos() @@ -199,18 +213,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra public DhChunkPos getPlayerChunkPos() { #if MC_VER < MC_1_17_1 - ChunkPos playerPos = new ChunkPos(getPlayer().blockPosition()); + ChunkPos playerPos = new ChunkPos(this.getPlayer().blockPosition()); #else ChunkPos playerPos = this.getPlayer().chunkPosition(); #endif return new DhChunkPos(playerPos.x, playerPos.z); } - public ModelManager getModelManager() - { - return this.mc.getModelManager(); - } - @Nullable @Override public IClientLevelWrapper getWrappedClientLevel() @@ -222,7 +231,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra @Nullable public IClientLevelWrapper getWrappedClientLevel(boolean bypassMultiverse) { - ClientLevel level = this.mc.level; + ClientLevel level = MINECRAFT.level; if (level == null) { return null; @@ -231,25 +240,18 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra return ClientLevelWrapper.getWrapper(level, bypassMultiverse); } - /** Please move over to getInstallationDirectory() */ - @Deprecated - @Override - public File getGameDirectory() - { - return this.getInstallationDirectory(); - } - @Override public IProfilerWrapper getProfiler() { if (this.profilerWrapper == null) { - this.profilerWrapper = new ProfilerWrapper(this.mc.getProfiler()); + this.profilerWrapper = new ProfilerWrapper(MINECRAFT.getProfiler()); } - else if (this.mc.getProfiler() != this.profilerWrapper.profiler) + else if (MINECRAFT.getProfiler() != this.profilerWrapper.profiler) { - this.profilerWrapper.profiler = this.mc.getProfiler(); + this.profilerWrapper.profiler = MINECRAFT.getProfiler(); } + return this.profilerWrapper; } @@ -259,7 +261,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra { ArrayList worlds = new ArrayList(); - Iterable serverWorlds = this.mc.getSingleplayerServer().getAllLevels(); + Iterable serverWorlds = MINECRAFT.getSingleplayerServer().getAllLevels(); for (ServerLevel world : serverWorlds) { worlds.add(ServerLevelWrapper.getWrapper(world)); @@ -273,15 +275,12 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra @Override public void sendChatMessage(String string) { - LocalPlayer p = this.getPlayer(); - if (p == null) - { - return; - } + LocalPlayer player = this.getPlayer(); + if (player == null) return; #if MC_VER < MC_1_19_2 - p.sendMessage(new TextComponent(string), getPlayer().getUUID()); + player.sendMessage(new TextComponent(string), getPlayer().getUUID()); #else - p.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string)); + player.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string)); #endif } @@ -306,24 +305,15 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra } @Override - public Object getOptionsObject() - { - return this.mc.options; - } + public Object getOptionsObject() { return MINECRAFT.options; } @Override - public boolean isDedicatedServer() - { - return false; - } + public boolean isDedicatedServer() { return false; } @Override - public File getInstallationDirectory() - { - return this.mc.gameDirectory; - } + public File getInstallationDirectory() { return MINECRAFT.gameDirectory; } @Override - public void executeOnRenderThread(Runnable runnable) { this.mc.execute(runnable); } + public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); } } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java index e0ffe856e..b75e203d5 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java @@ -21,9 +21,7 @@ package com.seibel.distanthorizons.common.wrappers.minecraft; import java.awt.Color; import java.lang.invoke.MethodHandles; -import java.nio.FloatBuffer; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -38,10 +36,10 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.render.DhApiRenderProxy; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; #if MC_VER < MC_1_19_4 +import org.joml.Matrix4f; import org.joml.Vector3f; #else import org.joml.Matrix4f; @@ -55,9 +53,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOpt import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; -import com.seibel.distanthorizons.coreapi.util.math.Vec3d; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; +import com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor; @@ -81,7 +79,6 @@ import net.minecraft.world.level.material.FogType; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.apache.logging.log4j.Logger; -import org.joml.Matrix4f; /** @@ -415,7 +412,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper // so this will have to do for now IDimensionTypeWrapper dimensionType = level.getDimensionType(); - LightMapWrapper wrapper = this.lightmapByDimensionType.compute(dimensionType, (dimType, oldWrapper) -> new LightMapWrapper()); + LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper()); wrapper.uploadLightmap(lightPixels); } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java index b6ed1265c..4754ba04c 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java @@ -36,14 +36,6 @@ public class LightMapWrapper implements ILightMapWrapper public LightMapWrapper() { } - private void createLightmap(NativeImage image) - { - this.textureId = GL32.glGenTextures(); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId); - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(), - 0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null); - } - //=========// @@ -53,14 +45,25 @@ public class LightMapWrapper implements ILightMapWrapper public void uploadLightmap(NativeImage image) { int currentBind = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId); if (this.textureId == 0) { this.createLightmap(image); } + else + { + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId); + } image.upload(0, 0, 0, false); GL32.glBindTexture(GL32.GL_TEXTURE_2D, currentBind); } + private void createLightmap(NativeImage image) + { + this.textureId = GL32.glGenTextures(); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId); + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(), + 0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null); + } + @Override public void bind() diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java index 4be82b6c6..2c14b8fdf 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/ServerPlayerWrapper.java @@ -5,7 +5,7 @@ import com.google.common.collect.MapMaker; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3d; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.world.phys.Vec3; diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java index cb44d4831..c558c86bd 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java @@ -1,14 +1,14 @@ package com.seibel.distanthorizons.common.wrappers.world; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper; import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper; import com.seibel.distanthorizons.common.wrappers.block.cache.ClientBlockDetailMap; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; -import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; +import com.seibel.distanthorizons.core.level.*; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; @@ -19,6 +19,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; +import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.chunk.ChunkAccess; @@ -39,14 +40,18 @@ import net.minecraft.world.level.chunk.status.ChunkStatus; public class ClientLevelWrapper implements IClientLevelWrapper { private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName()); - private static final ConcurrentHashMap LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>(); // TODO can leak private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class); + private static final Minecraft MINECRAFT = Minecraft.getInstance(); + private final ClientLevel level; private final ClientBlockDetailMap blockMap = new ClientBlockDetailMap(this); private BlockStateWrapper dirtBlockWrapper; private BiomeWrapper plainsBiomeWrapper; + @Deprecated // TODO circular references are bad + private IDhLevel parentDhLevel; @@ -94,7 +99,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper { try { - Iterable serverLevels = MinecraftClientWrapper.INSTANCE.mc.getSingleplayerServer().getAllLevels(); + Iterable serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels(); // attempt to find the server level with the same dimension type // TODO this assumes only one level per dimension type, the SubDimensionLevelMatcher will need to be added for supporting multiple levels per dimension @@ -191,7 +196,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); } @Override - public int getHeight() { return this.level.getHeight(); } + public int getMaxHeight() { return this.level.getHeight(); } @Override public int getMinHeight() @@ -240,7 +245,37 @@ public class ClientLevelWrapper implements IClientLevelWrapper public ClientLevel getWrappedMcObject() { return this.level; } @Override - public void onUnload() { LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level); } + public void onUnload() + { + LEVEL_WRAPPER_BY_CLIENT_LEVEL.remove(this.level); + this.parentDhLevel = null; + } + + + + //===================// + // generic rendering // + //===================// + + @Override + public void setParentLevel(IDhLevel parentLevel) { this.parentDhLevel = parentLevel; } + + @Override + public IDhApiCustomRenderRegister getRenderRegister() + { + if (this.parentDhLevel == null) + { + return null; + } + + return this.parentDhLevel.getGenericRenderer(); + } + + + + //================// + // base overrides // + //================// @Override public String toString() diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java index 447e184bd..5504e96c0 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java @@ -23,19 +23,18 @@ import java.io.File; import java.util.concurrent.ConcurrentHashMap; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper; import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper; -import com.seibel.distanthorizons.common.wrappers.block.cache.ServerBlockDetailMap; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; -import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper; +import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; -import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import net.minecraft.server.level.ServerLevel; @@ -49,7 +48,6 @@ import net.minecraft.world.level.chunk.status.ChunkStatus; #endif import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; /** * @version 2022-9-16 @@ -59,8 +57,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final ConcurrentHashMap LEVEL_WRAPPER_BY_SERVER_LEVEL = new ConcurrentHashMap<>(); - final ServerLevel level; - ServerBlockDetailMap blockMap = new ServerBlockDetailMap(this); + private final ServerLevel level; + @Deprecated // TODO circular references are bad + private IDhLevel parentDhLevel; @@ -81,19 +80,6 @@ public class ServerLevelWrapper implements IServerLevelWrapper // methods // //=========// - @Nullable - @Override - public IClientLevelWrapper tryGetClientLevelWrapper() - { - MinecraftClientWrapper client = MinecraftClientWrapper.INSTANCE; - if (client.mc.level == null) - { - return null; - } - - return ClientLevelWrapper.getWrapper(client.mc.level); - } - @Override public File getSaveFolder() { @@ -133,7 +119,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper } @Override - public int getHeight() + public int getMaxHeight() { return this.level.getHeight(); } @@ -147,6 +133,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper return this.level.getMinBuildHeight(); #endif } + @Override public IChunkWrapper tryGetChunk(DhChunkPos pos) { @@ -183,18 +170,33 @@ public class ServerLevelWrapper implements IServerLevelWrapper } @Override - public ServerLevel getWrappedMcObject() - { - return this.level; - } + public ServerLevel getWrappedMcObject() { return this.level; } @Override public void onUnload() { LEVEL_WRAPPER_BY_SERVER_LEVEL.remove(this.level); } + @Override - public String toString() + public void setParentLevel(IDhLevel parentLevel) { this.parentDhLevel = parentLevel; } + + @Override + public IDhApiCustomRenderRegister getRenderRegister() { - return "Wrapped{" + this.level.toString() + "@" + this.getDimensionName() + "}"; + if (this.parentDhLevel == null) + { + return null; + } + + return this.parentDhLevel.getGenericRenderer(); } + + + //================// + // base overrides // + //================// + + @Override + public String toString() { return "Wrapped{" + this.level.toString() + "@" + this.getDimensionName() + "}"; } + } \ No newline at end of file diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java index b7a46b875..bd01cc0b4 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/BatchGenerationEnvironment.java @@ -346,8 +346,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv } else if (event.hasTimeout(Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get(), TimeUnit.SECONDS)) { - EVENT_LOGGER.error("Batching World Generator: " + event + " timed out and terminated! Please lower your CPU load."); - EVENT_LOGGER.info("Dump PrefEvent: " + event.timer); + EVENT_LOGGER.warn( + "Batching World Generator: [" + event + "] timed out and terminated after ["+Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get()+"] seconds. " + + "\nYour computer might be overloaded or your world gen mods might be causing world gen to take longer than expected. " + + "\nEither increase DH's world gen timeout or reduce your computer's CPU load."); + EVENT_LOGGER.debug("Dump PrefEvent: " + event.timer); try { if (!event.terminate()) @@ -416,12 +419,15 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv CompoundTag chunkData = this.getChunkNbtData(chunkPos); newChunk = this.loadOrMakeChunk(chunkPos, chunkData); - // get chunk lighting - ChunkLoader.CombinedChunkLightStorage combinedLights = ChunkLoader.readLight(newChunk, chunkData); - if (combinedLights != null) + if (Config.Client.Advanced.LodBuilding.pullLightingForPregeneratedChunks.get()) { - chunkSkyLightingByDhPos.put(dhChunkPos, combinedLights.skyLightStorage); - chunkBlockLightingByDhPos.put(dhChunkPos, combinedLights.blockLightStorage); + // attempt to get chunk lighting + ChunkLoader.CombinedChunkLightStorage combinedLights = ChunkLoader.readLight(newChunk, chunkData); + if (combinedLights != null) + { + chunkSkyLightingByDhPos.put(dhChunkPos, combinedLights.skyLightStorage); + chunkBlockLightingByDhPos.put(dhChunkPos, combinedLights.blockLightStorage); + } } } catch (RuntimeException loadChunkError) @@ -471,7 +477,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, region, this.serverlevel.getLevelWrapper()); chunkWrapperList.set(x, z, chunkWrapper); - // try getting the chunk lighting + // try setting the wrapper's lighting if (chunkBlockLightingByDhPos.containsKey(chunkWrapper.getChunkPos())) { chunkWrapper.setBlockLightStorage(chunkBlockLightingByDhPos.get(chunkWrapper.getChunkPos())); @@ -479,10 +485,6 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv chunkWrapper.setUseDhLighting(true); chunkWrapper.setIsDhLightCorrect(true); } - else - { - int k = 0; - } } }); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java index fac555faa..bd34e50b5 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/mimicObject/ChunkLoader.java @@ -252,8 +252,8 @@ public class ChunkLoader biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS)); #endif #endif - int i = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif - LevelChunkSection[] chunkSections = new LevelChunkSection[i]; + int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif + LevelChunkSection[] chunkSections = new LevelChunkSection[sectionYIndex]; boolean isLightOn = chunkData.getBoolean("isLightOn"); boolean hasSkyLight = level.dimensionType().hasSkyLight(); @@ -288,7 +288,7 @@ public class ChunkLoader #endif blockStateContainer = tagSection.contains("block_states", 10) - ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)) + ? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logBlockDeserializationWarning(chunkPos, sectionYPos, string)) #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else @@ -303,7 +303,7 @@ public class ChunkLoader #else biomeContainer = tagSection.contains("biomes", 10) - ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)) + ? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string)) #if MC_VER < MC_1_20_6 .getOrThrow(false, LOGGER::error) #else @@ -495,9 +495,13 @@ public class ChunkLoader } } - private static void logErrors(ChunkPos chunkPos, int i, String string) + private static void logBlockDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message) { - LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string); + LOGGER.warn("Unable to deserialize blocks for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+message+"]. This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); + } + private static void logBiomeDeserializationWarning(ChunkPos chunkPos, int sectionYIndex, String message) + { + LOGGER.warn("Unable to deserialize biomes for chunk section [" + chunkPos.x + ", " + sectionYIndex + ", " + chunkPos.z + "], error: ["+message+"]. This can probably be ignored, although if your world looks wrong, optimizing it via the single player menu then deleting your DH database(s) should fix the problem."); } diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java index 7fdce78f0..f3cf3302f 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepBiomes.java @@ -61,7 +61,12 @@ public final class StepBiomes for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + if (chunkWrapper.getStatus().isOrAfter(STATUS)) + { + // this chunk has already generated this step + continue; + } + else if (chunk instanceof ProtoChunk) { #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java index 5ae538825..8d8bfb182 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepFeatures.java @@ -59,8 +59,12 @@ public final class StepFeatures for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (!chunkWrapper.getStatus().isOrAfter(STATUS) - && chunk instanceof ProtoChunk) + if (chunkWrapper.getStatus().isOrAfter(STATUS)) + { + // this chunk has already generated this step + continue; + } + else if (chunk instanceof ProtoChunk) { #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java index e90819967..c5dc640e8 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureReference.java @@ -59,7 +59,12 @@ public final class StepStructureReference for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + if (chunkWrapper.getStatus().isOrAfter(STATUS)) + { + // this chunk has already generated this step + continue; + } + else if (chunk instanceof ProtoChunk) { #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java index 8c53a0c12..5dcb57468 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepStructureStart.java @@ -76,7 +76,12 @@ public final class StepStructureStart for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + if (chunkWrapper.getStatus().isOrAfter(STATUS)) + { + // this chunk has already generated this step + continue; + } + else if (chunk instanceof ProtoChunk) { #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); @@ -88,12 +93,12 @@ public final class StepStructureStart } #if MC_VER < MC_1_19_2 - if (environment.params.worldGenSettings.generateFeatures()) + if (this.environment.params.worldGenSettings.generateFeatures()) { #elif MC_VER < MC_1_19_4 - if (environment.params.worldGenSettings.generateStructures()) { + if (this.environment.params.worldGenSettings.generateStructures()) { #else - if (environment.params.worldOptions.generateStructures()) + if (this.environment.params.worldOptions.generateStructures()) { #endif for (ChunkAccess chunk : chunksToDo) diff --git a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java index 0e61d70a2..56b247783 100644 --- a/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java +++ b/common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/step/StepSurface.java @@ -58,7 +58,12 @@ public final class StepSurface for (ChunkWrapper chunkWrapper : chunkWrappers) { ChunkAccess chunk = chunkWrapper.getChunk(); - if (!chunkWrapper.getStatus().isOrAfter(STATUS)) + if (chunkWrapper.getStatus().isOrAfter(STATUS)) + { + // this chunk has already generated this step + continue; + } + else if (chunk instanceof ProtoChunk) { #if MC_VER < MC_1_21 ((ProtoChunk) chunk).setStatus(STATUS); diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java index 3075db18f..0e29b817b 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/FabricClientProxy.java @@ -31,11 +31,11 @@ import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.network.messages.NetworkMessage; +import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.fabric.wrappers.modAccessor.SodiumAccessor; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -57,6 +57,7 @@ import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import java.nio.FloatBuffer; #endif import java.util.HashSet; +import java.util.concurrent.ThreadPoolExecutor; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.InteractionResult; @@ -125,6 +126,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy }); // (kinda) block break event + // Since fabric doesn't have a client-side break-block API event, this is the next best thing AttackBlockCallback.EVENT.register((player, level, interactionHand, blockPos, direction) -> { // if we have access to the server, use the chunk save event instead @@ -132,18 +134,27 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy { if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ())) { - // Since fabric doesn't have a client-side break-block API event, this is the next best thing - ChunkAccess chunk = level.getChunk(blockPos); - if (chunk != null) + // executor to prevent locking up the render/event thread + // if the getChunk() takes longer than expected + // (which can be caused by certain mods) + ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) { - //LOGGER.trace("attack block at blockPos: " + blockPos); - - IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); - SharedApi.INSTANCE.chunkBlockChangedEvent( - new ChunkWrapper(chunk, level, wrappedLevel), - wrappedLevel - ); - } + executor.execute(() -> + { + ChunkAccess chunk = level.getChunk(blockPos); + if (chunk != null) + { + //LOGGER.trace("attack block at blockPos: " + blockPos); + + IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); + SharedApi.INSTANCE.chunkBlockChangedEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + } + }); + } } } @@ -152,27 +163,37 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy }); // (kinda) block place event + // Since fabric doesn't have a client-side place-block API event, this is the next best thing UseBlockCallback.EVENT.register((player, level, hand, hitResult) -> { // if we have access to the server, use the chunk save event instead if (MC.clientConnectedToDedicatedServer()) { - if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ())) + if (hitResult.getType() == HitResult.Type.BLOCK + && !hitResult.isInside()) { - // Since fabric doesn't have a client-side place-block API event, this is the next best thing - if (hitResult.getType() == HitResult.Type.BLOCK - && !hitResult.isInside()) + if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ())) { - ChunkAccess chunk = level.getChunk(hitResult.getBlockPos()); - if (chunk != null) + // executor to prevent locking up the render/event thread + // if the getChunk() takes longer than expected + // (which can be caused by certain mods) + ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) { - //LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos()); - - IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); - SharedApi.INSTANCE.chunkBlockChangedEvent( - new ChunkWrapper(chunk, level, wrappedLevel), - wrappedLevel - ); + executor.execute(() -> + { + ChunkAccess chunk = level.getChunk(hitResult.getBlockPos()); + if (chunk != null) + { + //LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos()); + + IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level); + SharedApi.INSTANCE.chunkBlockChangedEvent( + new ChunkWrapper(chunk, level, wrappedLevel), + wrappedLevel + ); + } + }); } } } diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java index 12bbb0421..8b729e082 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/mixins/client/MixinLevelRenderer.java @@ -22,6 +22,7 @@ package com.seibel.distanthorizons.fabric.mixins.client; import com.mojang.blaze3d.vertex.PoseStack; #if MC_VER < MC_1_19_4 import com.mojang.math.Matrix4f; +import org.lwjgl.opengl.GL32; #else import org.joml.Matrix4f; #endif @@ -29,23 +30,17 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.core.api.internal.ClientApi; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LightTexture; import com.seibel.distanthorizons.core.config.Config; -import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; -import net.minecraft.world.level.lighting.LevelLightEngine; -import org.lwjgl.opengl.GL15; 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; @@ -99,7 +94,7 @@ public class MixinLevelRenderer #if MC_VER == MC_1_16_5 // get the matrices from the OpenGL fixed pipeline float[] mcProjMatrixRaw = new float[16]; - GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw); + GL32.glGetFloatv(GL32.GL_PROJECTION_MATRIX, mcProjMatrixRaw); Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw); mcProjectionMatrix.transpose(); @@ -110,13 +105,14 @@ public class MixinLevelRenderer Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose()); Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix); #else - // get the matrices directly from MC + // MC combined the model view and projection matricies Mat4f mcModelViewMatrix = McObjectConverter.Convert(projectionMatrix); Mat4f mcProjectionMatrix = new Mat4f(); mcProjectionMatrix.setIdentity(); #endif - if (renderType.equals(RenderType.translucent())) { + if (renderType.equals(RenderType.translucent())) + { ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level), mcModelViewMatrix, mcProjectionMatrix, diff --git a/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/SodiumAccessor.java b/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/SodiumAccessor.java index 7145d673a..bb4764c25 100644 --- a/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/SodiumAccessor.java +++ b/fabric/src/main/java/com/seibel/distanthorizons/fabric/wrappers/modAccessor/SodiumAccessor.java @@ -24,7 +24,7 @@ import java.util.stream.Collectors; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; diff --git a/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java b/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java index a4721780a..9906f8f05 100644 --- a/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java +++ b/forge/src/main/java/com/seibel/distanthorizons/forge/ForgeClientProxy.java @@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -61,6 +62,8 @@ import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import org.lwjgl.opengl.GL32; +import java.util.concurrent.ThreadPoolExecutor; + /** * This handles all events sent to the client, * and is the starting point for most of the mod. @@ -180,8 +183,15 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy LevelAccessor level = event.getLevel(); #endif - ChunkAccess chunk = level.getChunk(event.getPos()); - this.onBlockChangeEvent(level, chunk); + ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) + { + executor.execute(() -> + { + ChunkAccess chunk = level.getChunk(event.getPos()); + this.onBlockChangeEvent(level, chunk); + }); + } } @SubscribeEvent public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event) @@ -199,8 +209,15 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy LevelAccessor level = event.getLevel(); #endif - ChunkAccess chunk = level.getChunk(event.getPos()); - this.onBlockChangeEvent(level, chunk); + ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) + { + executor.execute(() -> + { + ChunkAccess chunk = level.getChunk(event.getPos()); + this.onBlockChangeEvent(level, chunk); + }); + } } private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk) { diff --git a/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinLevelRenderer.java b/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinLevelRenderer.java index 9eb2d9394..2b95ac702 100644 --- a/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinLevelRenderer.java +++ b/forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinLevelRenderer.java @@ -22,6 +22,10 @@ package com.seibel.distanthorizons.forge.mixins.client; import com.mojang.blaze3d.vertex.PoseStack; #if MC_VER < MC_1_19_4 import com.mojang.math.Matrix4f; +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.LightTexture; #else import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; @@ -34,13 +38,9 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.api.internal.ClientApi; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; -import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; +import com.seibel.distanthorizons.core.util.math.Mat4f; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -50,7 +50,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; -import java.nio.FloatBuffer; #if MC_VER < MC_1_17_1 import org.lwjgl.opengl.GL15; diff --git a/gradle.properties b/gradle.properties index 0274147d8..cfb14f8ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.caching=true # Mod Info mod_name=DistantHorizons mod_version=2.1.3-a-dev -api_version=2.1.0 +api_version=3.0.0 maven_group=com.seibel.distanthorizons mod_readable_name=Distant Horizons mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow. diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java index 598a15cc5..f1712d7fb 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/NeoforgeClientProxy.java @@ -28,13 +28,13 @@ import com.seibel.distanthorizons.core.api.internal.ClientApi; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.math.Mat4f; +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.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -import com.seibel.distanthorizons.coreapi.ModInfo; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import net.minecraft.world.level.LevelAccessor; import net.minecraft.client.multiplayer.ClientLevel; @@ -165,12 +165,21 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy return; } - //LOGGER.trace("interact or block place event at blockPos: " + event.getPos()); - - LevelAccessor level = event.getLevel(); - - ChunkAccess chunk = level.getChunk(event.getPos()); - this.onBlockChangeEvent(level, chunk); + // executor to prevent locking up the render/event thread + // if the getChunk() takes longer than expected + // (which can be caused by certain mods) + var executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) + { + executor.execute(() -> + { + //LOGGER.trace("interact or block place event at blockPos: " + event.getPos()); + + LevelAccessor level = event.getLevel(); + ChunkAccess chunk = level.getChunk(event.getPos()); + this.onBlockChangeEvent(level, chunk); + }); + } } @SubscribeEvent public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event) @@ -180,12 +189,21 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy return; } - //LOGGER.trace("break or block attack at blockPos: " + event.getPos()); - - LevelAccessor level = event.getLevel(); - - ChunkAccess chunk = level.getChunk(event.getPos()); - this.onBlockChangeEvent(level, chunk); + // executor to prevent locking up the render/event thread + // if the getChunk() takes longer than expected + // (which can be caused by certain mods) + var executor = ThreadPoolUtil.getFileHandlerExecutor(); + if (executor != null) + { + executor.execute(() -> + { + //LOGGER.trace("break or block attack at blockPos: " + event.getPos()); + + LevelAccessor level = event.getLevel(); + ChunkAccess chunk = level.getChunk(event.getPos()); + this.onBlockChangeEvent(level, chunk); + }); + } } private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk) { diff --git a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java index 8c3c0506c..93e1a06a7 100644 --- a/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java +++ b/neoforge/src/main/java/com/seibel/distanthorizons/neoforge/mixins/client/MixinLevelRenderer.java @@ -24,6 +24,7 @@ import com.mojang.blaze3d.vertex.PoseStack; #if MC_VER < MC_1_19_4 import com.mojang.math.Matrix4f; #else +import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.neoforge.NeoforgeClientProxy; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; @@ -36,7 +37,6 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.api.internal.ClientApi; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.RenderType; diff --git a/wipelod.ps1 b/wipelod.ps1 new file mode 100644 index 000000000..f8cea2d8e --- /dev/null +++ b/wipelod.ps1 @@ -0,0 +1,4 @@ +Remove-Item -Recurse -Force "run/client/Distant_Horizons_server_data" + +Get-ChildItem -Path "run/server" -Recurse -Filter "Distant_Horizons" | ForEach-Object { Remove-Item -Recurse -Force $_.FullName } +Get-ChildItem -Path "run/server" -Recurse -Filter "DistantHorizons.sqlite" | ForEach-Object { Remove-Item -Force $_.FullName } \ No newline at end of file