Apply editorconfig auto formatting

This commit is contained in:
James Seibel
2023-08-14 21:16:13 -05:00
parent 2af274171c
commit f564755d66
107 changed files with 4487 additions and 3822 deletions
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common;
import com.seibel.distanthorizons.common.forge.LodForgeMethodCaller;
@@ -28,35 +28,36 @@ import com.seibel.distanthorizons.core.config.ConfigBase;
/**
* This is the common main class
*
* @author Ran
*/
public class LodCommonMain
public class LodCommonMain
{
public static boolean forge = false;
public static LodForgeMethodCaller forgeMethodCaller;
public static boolean forge = false;
public static LodForgeMethodCaller forgeMethodCaller;
public static void startup(LodForgeMethodCaller forgeMethodCaller)
public static void startup(LodForgeMethodCaller forgeMethodCaller)
{
if (forgeMethodCaller != null)
if (forgeMethodCaller != null)
{
LodCommonMain.forge = true;
LodCommonMain.forgeMethodCaller = forgeMethodCaller;
}
LodCommonMain.forge = true;
LodCommonMain.forgeMethodCaller = forgeMethodCaller;
}
DependencySetup.createSharedBindings();
SharedApi.init();
DependencySetup.createSharedBindings();
SharedApi.init();
// if (!serverSided) {
// new NetworkReceiver().register_Client();
// } else {
// new NetworkReceiver().register_Server();
// }
}
public static void initConfig()
}
public static void initConfig()
{
ConfigBase.INSTANCE = new ConfigBase(ModInfo.ID, ModInfo.NAME, Config.class,1);
ConfigBase.INSTANCE = new ConfigBase(ModInfo.ID, ModInfo.NAME, Config.class, 1);
Config.completeDelayedSetup();
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.forge;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
@@ -36,14 +36,17 @@ import java.util.Random;
/**
* used for calling methods that forge modified
* (forge modifies vanilla methods for some reason)
*
* @author Ran
*/
public interface LodForgeMethodCaller {
#if PRE_MC_1_19_2
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random); // FIXME: For 1.19
#else
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, RandomSource random); // FIXME: For 1.19
public interface LodForgeMethodCaller
{
#if PRE_MC_1_19_2
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random); // FIXME: For 1.19
#else
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, RandomSource random); // FIXME: For 1.19
#endif
int colorResolverGetColor(ColorResolver resolver, Biome biome, double x, double z);
int colorResolverGetColor(ColorResolver resolver, Biome biome, double x, double z);
}
@@ -1,8 +1,10 @@
package com.seibel.distanthorizons.common.rendering;
#if PRE_MC_1_19_4
import com.mojang.math.Matrix4f;
#else
import org.joml.Matrix4f;
#endif
import com.seibel.distanthorizons.core.config.Config;
@@ -48,28 +48,28 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSha
public class DependencySetup
{
public static void createSharedBindings()
{
SingletonInjector.INSTANCE.bind(ILangWrapper.class, LangWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
DependencySetupDoneCheck.isDone = true;
}
//@Environment(EnvType.SERVER)
public static void createServerBindings()
public static void createSharedBindings()
{
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftDedicatedServerWrapper.INSTANCE);
}
//@Environment(EnvType.CLIENT)
public static void createClientBindings()
SingletonInjector.INSTANCE.bind(ILangWrapper.class, LangWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
DependencySetupDoneCheck.isDone = true;
}
//@Environment(EnvType.SERVER)
public static void createServerBindings()
{
SingletonInjector.INSTANCE.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IReflectionHandler.class, ReflectionHandler.INSTANCE);
}
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftDedicatedServerWrapper.INSTANCE);
}
//@Environment(EnvType.CLIENT)
public static void createClientBindings()
{
SingletonInjector.INSTANCE.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IReflectionHandler.class, ReflectionHandler.INSTANCE);
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers;
import java.util.function.Supplier;
@@ -26,6 +26,6 @@ public class DependencySetupDoneCheck
// TODO move to DependencySetup
public static boolean isDone = false;
// TODO why is this here and what is its purpose?
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> {return false;});
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> { return false; });
}
@@ -47,53 +47,56 @@ import net.minecraft.world.level.ChunkPos;
*/
public class McObjectConverter
{
private static int bufferIndex(int x, int y) {
return y * 4 + x;
}
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
private static void storeMatrix(Matrix4f matrix, FloatBuffer buffer) {
private static int bufferIndex(int x, int y)
{
return y * 4 + x;
}
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
private static void storeMatrix(Matrix4f matrix, FloatBuffer buffer)
{
#if PRE_MC_1_19_4
matrix.store(buffer);
matrix.store(buffer);
#else
// Mojang starts to use joml's Matrix4f libary in 1.19.3 so we copy their store method and use it here if its newer than 1.19.3
buffer.put(bufferIndex(0, 0), matrix.m00());
buffer.put(bufferIndex(0, 1), matrix.m01());
buffer.put(bufferIndex(0, 2), matrix.m02());
buffer.put(bufferIndex(0, 3), matrix.m03());
buffer.put(bufferIndex(1, 0), matrix.m10());
buffer.put(bufferIndex(1, 1), matrix.m11());
buffer.put(bufferIndex(1, 2), matrix.m12());
buffer.put(bufferIndex(1, 3), matrix.m13());
buffer.put(bufferIndex(2, 0), matrix.m20());
buffer.put(bufferIndex(2, 1), matrix.m21());
buffer.put(bufferIndex(2, 2), matrix.m22());
buffer.put(bufferIndex(2, 3), matrix.m23());
buffer.put(bufferIndex(3, 0), matrix.m30());
buffer.put(bufferIndex(3, 1), matrix.m31());
buffer.put(bufferIndex(3, 2), matrix.m32());
buffer.put(bufferIndex(3, 3), matrix.m33());
// Mojang starts to use joml's Matrix4f libary in 1.19.3 so we copy their store method and use it here if its newer than 1.19.3
buffer.put(bufferIndex(0, 0), matrix.m00());
buffer.put(bufferIndex(0, 1), matrix.m01());
buffer.put(bufferIndex(0, 2), matrix.m02());
buffer.put(bufferIndex(0, 3), matrix.m03());
buffer.put(bufferIndex(1, 0), matrix.m10());
buffer.put(bufferIndex(1, 1), matrix.m11());
buffer.put(bufferIndex(1, 2), matrix.m12());
buffer.put(bufferIndex(1, 3), matrix.m13());
buffer.put(bufferIndex(2, 0), matrix.m20());
buffer.put(bufferIndex(2, 1), matrix.m21());
buffer.put(bufferIndex(2, 2), matrix.m22());
buffer.put(bufferIndex(2, 3), matrix.m23());
buffer.put(bufferIndex(3, 0), matrix.m30());
buffer.put(bufferIndex(3, 1), matrix.m31());
buffer.put(bufferIndex(3, 2), matrix.m32());
buffer.put(bufferIndex(3, 3), matrix.m33());
#endif
}
/** 4x4 float matrix converter */
public static Mat4f Convert(Matrix4f mcMatrix)
{
FloatBuffer buffer = FloatBuffer.allocate(16);
storeMatrix(mcMatrix, buffer);
Mat4f matrix = new Mat4f(buffer);
}
/** 4x4 float matrix converter */
public static Mat4f Convert(Matrix4f mcMatrix)
{
FloatBuffer buffer = FloatBuffer.allocate(16);
storeMatrix(mcMatrix, buffer);
Mat4f matrix = new Mat4f(buffer);
#if PRE_MC_1_19_4
matrix.transpose(); // In 1.19.3 and later, we no longer need to transpose it
matrix.transpose(); // In 1.19.3 and later, we no longer need to transpose it
#endif
return matrix;
}
static final Direction[] directions;
static final EDhDirection[] lodDirections;
static {
EDhDirection[] lodDirs = EDhDirection.values();
directions = new Direction[lodDirs.length];
lodDirections = new EDhDirection[lodDirs.length];
return matrix;
}
static final Direction[] directions;
static final EDhDirection[] lodDirections;
static
{
EDhDirection[] lodDirs = EDhDirection.values();
directions = new Direction[lodDirs.length];
lodDirections = new EDhDirection[lodDirs.length];
for (EDhDirection lodDir : lodDirs)
{
Direction dir;
@@ -129,39 +132,43 @@ public class McObjectConverter
directions[lodDir.ordinal()] = dir;
lodDirections[dir.ordinal()] = lodDir;
}
}
public static BlockPos Convert(DhBlockPos wrappedPos) {
return new BlockPos(wrappedPos.x, wrappedPos.y, wrappedPos.z);
}
public static ChunkPos Convert(DhChunkPos wrappedPos) {
return new ChunkPos(wrappedPos.x, wrappedPos.z);
}
public static Direction Convert(EDhDirection lodDirection)
{
return directions[lodDirection.ordinal()];
}
public static EDhDirection Convert(Direction direction)
{
return lodDirections[direction.ordinal()];
}
public static void DebugCheckAllPackers() {
BiConsumer<Integer, Integer> func = (x, z) -> DhChunkPos._DebugCheckPacker(x,z,ChunkPos.asLong(x,z));
func.accept(0,0);
func.accept(12345,134);
func.accept(-12345,-134);
func.accept(-30000000/16,30000000/16);
func.accept(30000000/16,-30000000/16);
func.accept(30000000/16,30000000/16);
func.accept(-30000000/16,-30000000/16);
Consumer<BlockPos> func2 = (p) -> DhBlockPos._DebugCheckPacker(p.getX(),p.getY(),p.getZ(),p.asLong());
func2.accept(new BlockPos(0,0,0));
func2.accept(new BlockPos(12345,134,123));
func2.accept(new BlockPos(-12345,-134,-80));
func2.accept(new BlockPos(-30000000, 2047, 30000000));
func2.accept(new BlockPos(30000000, -2048, -30000000));
func2.accept(new BlockPos(30000000, 2047, 30000000));
func2.accept(new BlockPos(-30000000, -2048, -30000000));
}
}
public static BlockPos Convert(DhBlockPos wrappedPos)
{
return new BlockPos(wrappedPos.x, wrappedPos.y, wrappedPos.z);
}
public static ChunkPos Convert(DhChunkPos wrappedPos)
{
return new ChunkPos(wrappedPos.x, wrappedPos.z);
}
public static Direction Convert(EDhDirection lodDirection)
{
return directions[lodDirection.ordinal()];
}
public static EDhDirection Convert(Direction direction)
{
return lodDirections[direction.ordinal()];
}
public static void DebugCheckAllPackers()
{
BiConsumer<Integer, Integer> func = (x, z) -> DhChunkPos._DebugCheckPacker(x, z, ChunkPos.asLong(x, z));
func.accept(0, 0);
func.accept(12345, 134);
func.accept(-12345, -134);
func.accept(-30000000 / 16, 30000000 / 16);
func.accept(30000000 / 16, -30000000 / 16);
func.accept(30000000 / 16, 30000000 / 16);
func.accept(-30000000 / 16, -30000000 / 16);
Consumer<BlockPos> func2 = (p) -> DhBlockPos._DebugCheckPacker(p.getX(), p.getY(), p.getZ(), p.asLong());
func2.accept(new BlockPos(0, 0, 0));
func2.accept(new BlockPos(12345, 134, 123));
func2.accept(new BlockPos(-12345, -134, -80));
func2.accept(new BlockPos(-30000000, 2047, 30000000));
func2.accept(new BlockPos(30000000, -2048, -30000000));
func2.accept(new BlockPos(30000000, 2047, 30000000));
func2.accept(new BlockPos(-30000000, -2048, -30000000));
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers;
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
@@ -43,25 +43,27 @@ public class VersionConstants implements IVersionConstants
{
return 0;
}
@Override
public int getWorldGenerationCountPerThread()
{
return 1;
}
@Override
public boolean isVanillaRenderedChunkSquare()
{
return false;
}
@Override
public String getMinecraftVersion() {
public String getMinecraftVersion()
{
#if PRE_MC_1_19_2
return Minecraft.getInstance().getGame().getVersion().getId();
#else
return SharedConstants.getCurrentVersion().getId();
#endif
}
}
@@ -38,6 +38,7 @@ import java.io.IOException;
/**
* This handles creating abstract wrapper objects.
*
* @author James Seibel
* @version 2022-12-5
*/
@@ -74,8 +75,9 @@ public class WrapperFactory implements IWrapperFactory
/**
* Note: when this is updated for different MC versions, make sure you also update the documentation in
* {@link IDhApiWorldGenerator#generateChunks} and the type list in {@link WrapperFactory#createChunkWrapperErrorMessage}. <br><br>
*
*
* For full method documentation please see: {@link IWrapperFactory#createChunkWrapper}
*
* @see IWrapperFactory#createChunkWrapper
*/
public IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException
@@ -105,14 +107,14 @@ public class WrapperFactory implements IWrapperFactory
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
ChunkAccess chunk = (ChunkAccess)objectArray[0];
ChunkAccess chunk = (ChunkAccess) objectArray[0];
// light source
if (!(objectArray[1] instanceof LevelReader))
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
LevelReader lightSource = (LevelReader)objectArray[1];
LevelReader lightSource = (LevelReader) objectArray[1];
return new ChunkWrapper(chunk, lightSource, /*A DH wrapped level isn't necessary*/null);
@@ -133,9 +135,9 @@ public class WrapperFactory implements IWrapperFactory
not implemented for this version of Minecraft!
#endif
}
/**
* Note: when this is updated for different MC versions,
* make sure you also update the documentation in {@link IDhApiWorldGenerator#generateChunks}.
/**
* Note: when this is updated for different MC versions,
* make sure you also update the documentation in {@link IDhApiWorldGenerator#generateChunks}.
*/
private static String createChunkWrapperErrorMessage(Object[] objectArray)
{
@@ -145,8 +147,8 @@ public class WrapperFactory implements IWrapperFactory
// MC 1.16, 1.18, 1.19, 1.20
#if POST_MC_1_17_1 || MC_1_16_5
message.append("["+ChunkAccess.class.getName()+"], \n");
message.append("["+LevelReader.class.getName()+"]. \n");
message.append("[" + ChunkAccess.class.getName() + "], \n");
message.append("[" + LevelReader.class.getName() + "]. \n");
#else
// See preprocessor comment in createChunkWrapper() for full documentation
not implemented for this version of Minecraft!
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -63,15 +64,15 @@ public class BiomeWrapper implements IBiomeWrapper
private static final Logger LOGGER = LogManager.getLogger();
#if PRE_MC_1_18_2
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
public final Biome biome;
#else
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
public final Holder<Biome> biome;
#if PRE_MC_1_18_2
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
public final Biome biome;
#else
public static final ConcurrentMap<Holder<Biome>, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
public final Holder<Biome> biome;
#endif
/**
/**
* Cached so it can be quickly used as a semi-stable hashing method. <br>
* This may also fix the issue where we can serialize and save after a level has been shut down.
*/
@@ -83,15 +84,15 @@ public class BiomeWrapper implements IBiomeWrapper
// constructors //
//==============//
static public IBiomeWrapper getBiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif biome)
{
return biomeWrapperMap.computeIfAbsent(biome, BiomeWrapper::new);
}
private BiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif biome)
{
this.biome = biome;
}
static public IBiomeWrapper getBiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif biome)
{
return biomeWrapperMap.computeIfAbsent(biome, BiomeWrapper::new);
}
private BiomeWrapper(#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif biome)
{
this.biome = biome;
}
@@ -100,34 +101,34 @@ public class BiomeWrapper implements IBiomeWrapper
//=========//
@Override
public String getName()
{
public String getName()
{
#if PRE_MC_1_18_2
return biome.toString();
return biome.toString();
#else
return this.biome.unwrapKey().orElse(Biomes.THE_VOID).registry().toString();
return this.biome.unwrapKey().orElse(Biomes.THE_VOID).registry().toString();
#endif
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null || this.getClass() != obj.getClass())
{
}
else if (obj == null || this.getClass() != obj.getClass())
{
return false;
}
}
BiomeWrapper that = (BiomeWrapper) obj;
// the serialized value is used so we can test the contents instead of the references
return Objects.equals(this.serialize(), that.serialize());
}
@Override
public int hashCode() { return Objects.hash(this.serialize()); }
BiomeWrapper that = (BiomeWrapper) obj;
// the serialized value is used so we can test the contents instead of the references
return Objects.equals(this.serialize(), that.serialize());
}
@Override
public int hashCode() { return Objects.hash(this.serialize()); }
@Override
public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
@@ -154,13 +155,13 @@ public class BiomeWrapper implements IBiomeWrapper
biomeName = this.biome.value().toString();
#endif
LOGGER.warn("unable to serialize: "+biomeName);
LOGGER.warn("unable to serialize: " + biomeName);
// shouldn't normally happen, but just in case
this.serializationResult = "";
}
else
{
this.serializationResult = resourceLocation.getNamespace()+":"+resourceLocation.getPath();
this.serializationResult = resourceLocation.getNamespace() + ":" + resourceLocation.getPath();
}
}
@@ -182,9 +183,9 @@ public class BiomeWrapper implements IBiomeWrapper
int separatorIndex = resourceLocationString.indexOf(":");
if (separatorIndex == -1)
{
throw new IOException("Unable to parse resource location string: ["+resourceLocationString+"].");
throw new IOException("Unable to parse resource location string: [" + resourceLocationString + "].");
}
ResourceLocation resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex+1));
ResourceLocation resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
try
@@ -200,7 +201,7 @@ public class BiomeWrapper implements IBiomeWrapper
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
if (unwrappedBiome == null)
{
LOGGER.warn("null biome string deserialized from string: "+resourceLocationString);
LOGGER.warn("null biome string deserialized from string: " + resourceLocationString);
}
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
#endif
@@ -209,12 +210,12 @@ public class BiomeWrapper implements IBiomeWrapper
}
catch (Exception e)
{
throw new IOException("Failed to deserialize the string ["+resourceLocationString+"] into a BiomeWrapper: "+e.getMessage(), e);
throw new IOException("Failed to deserialize the string [" + resourceLocationString + "] into a BiomeWrapper: " + e.getMessage(), e);
}
}
@Override
@Override
public Object getWrappedMcObject() { return this.biome; }
@Override
@@ -40,7 +40,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static final BlockStateWrapper AIR = new BlockStateWrapper(null);
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> cache = new ConcurrentHashMap<>();
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> cache = new ConcurrentHashMap<>();
/**
* Cached so it can be quickly used as a semi-stable hashing method. <br>
@@ -53,22 +53,22 @@ public class BlockStateWrapper implements IBlockStateWrapper
// constructors //
//==============//
public static BlockStateWrapper fromBlockState(BlockState blockState)
public static BlockStateWrapper fromBlockState(BlockState blockState)
{
if (blockState == null || blockState.isAir())
{
return AIR;
}
if (blockState == null || blockState.isAir())
{
return AIR;
}
return cache.computeIfAbsent(blockState, BlockStateWrapper::new);
}
public final BlockState blockState;
BlockStateWrapper(BlockState blockState)
{
this.blockState = blockState;
LOGGER.trace("Created BlockStateWrapper for ["+blockState+"]");
}
return cache.computeIfAbsent(blockState, BlockStateWrapper::new);
}
public final BlockState blockState;
BlockStateWrapper(BlockState blockState)
{
this.blockState = blockState;
LOGGER.trace("Created BlockStateWrapper for [" + blockState + "]");
}
@@ -97,7 +97,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
@Override
public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
public String serialize() // FIXME pass in level to prevent null pointers (or maybe just RegistryAccess?)
{
// cache the serialization result so it can be quickly used as a semi-stable hashing method
if (this.serializationResult == null)
@@ -120,7 +120,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
if (resourceLocation == null)
{
LOGGER.warn("unable to serialize: "+this.blockState);
LOGGER.warn("unable to serialize: " + this.blockState);
}
this.serializationResult = resourceLocation.getNamespace() + RESOURCE_LOCATION_SEPARATOR + resourceLocation.getPath()
@@ -144,18 +144,18 @@ public class BlockStateWrapper implements IBlockStateWrapper
int stateSeparatorIndex = resourceStateString.indexOf(STATE_STRING_SEPARATOR);
if (stateSeparatorIndex == -1)
{
throw new IOException("Unable to parse BlockState out of string: ["+resourceStateString+"].");
throw new IOException("Unable to parse BlockState out of string: [" + resourceStateString + "].");
}
String blockStatePropertiesString = resourceStateString.substring(stateSeparatorIndex+STATE_STRING_SEPARATOR.length());
resourceStateString = resourceStateString.substring(0, stateSeparatorIndex);
String blockStatePropertiesString = resourceStateString.substring(stateSeparatorIndex + STATE_STRING_SEPARATOR.length());
resourceStateString = resourceStateString.substring(0, stateSeparatorIndex);
// parse the resource location
int resourceSeparatorIndex = resourceStateString.indexOf(RESOURCE_LOCATION_SEPARATOR);
if (resourceSeparatorIndex == -1)
{
throw new IOException("Unable to parse Resource Location out of string: ["+resourceStateString+"].");
throw new IOException("Unable to parse Resource Location out of string: [" + resourceStateString + "].");
}
ResourceLocation resourceLocation = new ResourceLocation(resourceStateString.substring(0, resourceSeparatorIndex), resourceStateString.substring(resourceSeparatorIndex+1));
ResourceLocation resourceLocation = new ResourceLocation(resourceStateString.substring(0, resourceSeparatorIndex), resourceStateString.substring(resourceSeparatorIndex + 1));
@@ -190,16 +190,16 @@ public class BlockStateWrapper implements IBlockStateWrapper
// use the default if no state was found
if (foundState == null)
{
LOGGER.warn("Unable to find BlockState for Block ["+resourceLocation+"] with properties: ["+blockStatePropertiesString+"].");
LOGGER.warn("Unable to find BlockState for Block [" + resourceLocation + "] with properties: [" + blockStatePropertiesString + "].");
foundState = block.defaultBlockState();
}
return new BlockStateWrapper(foundState);
}
catch (Exception e)
{
throw new IOException("Failed to deserialize the string ["+resourceStateString+"] into a BlockStateWrapper: "+e.getMessage(), e);
throw new IOException("Failed to deserialize the string [" + resourceStateString + "] into a BlockStateWrapper: " + e.getMessage(), e);
}
}
}
/** used to compare and save BlockStates based on their properties */
private static String serializeBlockStateProperties(BlockState blockState)
@@ -209,7 +209,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
// alphabetically sort the list so they are always in the same order
List<net.minecraft.world.level.block.state.properties.Property<?>> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection);
sortedBlockPropteryList.sort((a,b) -> a.getName().compareTo(b.getName()));
sortedBlockPropteryList.sort((a, b) -> a.getName().compareTo(b.getName()));
StringBuilder stringBuilder = new StringBuilder();
@@ -232,26 +232,26 @@ public class BlockStateWrapper implements IBlockStateWrapper
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
}
if (obj == null || this.getClass() != obj.getClass())
{
if (obj == null || this.getClass() != obj.getClass())
{
return false;
}
}
BlockStateWrapper that = (BlockStateWrapper) obj;
// the serialized value is used so we can test the contents instead of the references
return Objects.equals(this.serialize(), that.serialize());
}
@Override
public int hashCode() { return Objects.hash(this.serialize()); }
BlockStateWrapper that = (BlockStateWrapper) obj;
// the serialized value is used so we can test the contents instead of the references
return Objects.equals(this.serialize(), that.serialize());
}
@Override
public int hashCode() { return Objects.hash(this.serialize()); }
@Override
@@ -262,17 +262,17 @@ public class BlockStateWrapper implements IBlockStateWrapper
public boolean isAir(BlockState blockState) { return blockState == null || blockState.isAir(); }
@Override
public boolean isSolid()
public boolean isSolid()
{
#if PRE_MC_1_20_1
return this.blockState.getMaterial().isSolid();
return this.blockState.getMaterial().isSolid();
#else
return !this.blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).isEmpty();
return !this.blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).isEmpty();
#endif
}
}
@Override
public boolean isLiquid()
public boolean isLiquid()
{
if (this.isAir())
{
@@ -280,11 +280,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
}
#if PRE_MC_1_20_1
return this.blockState.getMaterial().isLiquid();
return this.blockState.getMaterial().isLiquid();
#else
return !this.blockState.getFluidState().isEmpty();
return !this.blockState.getFluidState().isEmpty();
#endif
}
}
@Override
public String toString() { return this.serialize(); }
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.block;
@@ -24,36 +24,42 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
/**
* For wrapping/utilizing around TextureAtlasSprite
*
* @author Ran
*/
public class TextureAtlasSpriteWrapper {
/**
* This code is from Minecraft Forge
* Which is licensed under the terms of GNU Lesser General Public License
* as published by the Free Software Foundation version 2.1
* of the License.
*
* The code has been modified to use TextureAtlasSprite
*/
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
public class TextureAtlasSpriteWrapper
{
/**
* This code is from Minecraft Forge
* Which is licensed under the terms of GNU Lesser General Public License
* as published by the Free Software Foundation version 2.1
* of the License.
*
* The code has been modified to use TextureAtlasSprite
*/
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y)
{
#if PRE_MC_1_17_1
return sprite.mainImage[0].getPixelRGBA(
x + sprite.framesX[frameIndex] * sprite.getWidth(),
y + sprite.framesY[frameIndex] * sprite.getHeight());
#elif PRE_MC_1_19_4
if (sprite.animatedTexture != null) {
x += sprite.animatedTexture.getFrameX(frameIndex) * sprite.width;
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
}
return sprite.mainImage[0].getPixelRGBA(x, y);
if (sprite.animatedTexture != null)
{
x += sprite.animatedTexture.getFrameX(frameIndex) * sprite.width;
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
}
return sprite.mainImage[0].getPixelRGBA(x, y);
#else
if (sprite.contents().animatedTexture != null) {
x += sprite.contents().animatedTexture.getFrameX(frameIndex) * sprite.contents().width();
y += sprite.contents().animatedTexture.getFrameY(frameIndex) * sprite.contents().width();
}
return sprite.contents().originalImage.getPixelRGBA(x, y);
if (sprite.contents().animatedTexture != null)
{
x += sprite.contents().animatedTexture.getFrameX(frameIndex) * sprite.contents().width();
y += sprite.contents().animatedTexture.getFrameY(frameIndex) * sprite.contents().width();
}
return sprite.contents().originalImage.getPixelRGBA(x, y);
#endif
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.block;
import com.seibel.distanthorizons.common.LodCommonMain;
@@ -39,171 +39,205 @@ import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TintGetterOverrideFast implements BlockAndTintGetter {
LevelReader parent;
public TintGetterOverrideFast(LevelReader parent) {
this.parent = parent;
}
private Biome _getBiome(BlockPos pos) {
public class TintGetterOverrideFast implements BlockAndTintGetter
{
LevelReader parent;
public TintGetterOverrideFast(LevelReader parent)
{
this.parent = parent;
}
private Biome _getBiome(BlockPos pos)
{
#if POST_MC_1_18_2
return parent.getBiome(pos).value();
return parent.getBiome(pos).value();
#else
return parent.getBiome(pos);
#endif
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
if (LodCommonMain.forgeMethodCaller != null) {
return LodCommonMain.forgeMethodCaller.colorResolverGetColor(colorResolver, _getBiome(blockPos),
blockPos.getX(), blockPos.getZ());
} else {
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
}
}
@Override
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
@Override
public LevelLightEngine getLightEngine() {
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos) {
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos) {
return parent.getBlockEntity(blockPos);
}
@Override
public BlockState getBlockState(BlockPos blockPos) {
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos) {
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos) {
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel() {
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB) {
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult clip(ClipContext clipContext) {
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos) {
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getMaxBuildHeight() {
return parent.getMaxBuildHeight();
}
#if POST_MC_1_17_1
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public int getHeight() {
return parent.getHeight();
}
@Override
public int getMinBuildHeight() {
return parent.getMinBuildHeight();
}
@Override
public int getSectionsCount() {
return parent.getSectionsCount();
}
@Override
public int getMinSection() {
return parent.getMinSection();
}
@Override
public int getMaxSection() {
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) {
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i) {
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i) {
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i) {
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i) {
return parent.getSectionYFromSectionIndex(i);
}
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
if (LodCommonMain.forgeMethodCaller != null)
{
return LodCommonMain.forgeMethodCaller.colorResolverGetColor(colorResolver, _getBiome(blockPos),
blockPos.getX(), blockPos.getZ());
}
else
{
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
}
}
@Override
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
@Override
public LevelLightEngine getLightEngine()
{
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos)
{
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i)
{
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos)
{
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos)
{
return parent.getBlockEntity(blockPos);
}
@Override
public BlockState getBlockState(BlockPos blockPos)
{
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos)
{
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos)
{
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel()
{
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB)
{
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult clip(ClipContext clipContext)
{
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState)
{
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier)
{
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos)
{
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getMaxBuildHeight()
{
return parent.getMaxBuildHeight();
}
#if POST_MC_1_17_1
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType)
{
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext)
{
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public int getHeight()
{
return parent.getHeight();
}
@Override
public int getMinBuildHeight()
{
return parent.getMinBuildHeight();
}
@Override
public int getSectionsCount()
{
return parent.getSectionsCount();
}
@Override
public int getMinSection()
{
return parent.getMinSection();
}
@Override
public int getMaxSection()
{
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos)
{
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i)
{
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i)
{
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i)
{
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i)
{
return parent.getSectionYFromSectionIndex(i);
}
#endif
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.block;
import com.seibel.distanthorizons.common.LodCommonMain;
@@ -40,196 +40,230 @@ import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TintGetterOverrideSmooth implements BlockAndTintGetter {
LevelReader parent;
public int smoothingRange;
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange) {
this.parent = parent;
this.smoothingRange = smoothingRange;
}
private Biome _getBiome(BlockPos pos) {
public class TintGetterOverrideSmooth implements BlockAndTintGetter
{
LevelReader parent;
public int smoothingRange;
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange)
{
this.parent = parent;
this.smoothingRange = smoothingRange;
}
private Biome _getBiome(BlockPos pos)
{
#if POST_MC_1_18_2
return parent.getBiome(pos).value();
return parent.getBiome(pos).value();
#else
return parent.getBiome(pos);
return parent.getBiome(pos);
#endif
}
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
int i = smoothingRange;
if (i == 0)
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
int j = (i * 2 + 1) * (i * 2 + 1);
int k = 0;
int l = 0;
int m = 0;
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
while (cursor3D.advance())
{
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
int n;
if (LodCommonMain.forgeMethodCaller != null) {
n = LodCommonMain.forgeMethodCaller.colorResolverGetColor(colorResolver, _getBiome(mutableBlockPos),
mutableBlockPos.getX(), mutableBlockPos.getZ());
} else {
n = colorResolver.getColor(_getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
}
k += (n & 0xFF0000) >> 16;
l += (n & 0xFF00) >> 8;
m += n & 0xFF;
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
return calculateBlockTint(blockPos, colorResolver);
}
@Override
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
@Override
public LevelLightEngine getLightEngine() {
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos) {
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos) {
return parent.getBlockEntity(blockPos);
}
@Override
public BlockState getBlockState(BlockPos blockPos) {
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos) {
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos) {
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel() {
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB) {
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult clip(ClipContext clipContext) {
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos) {
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getMaxBuildHeight() {
return parent.getMaxBuildHeight();
}
#if POST_MC_1_17_1
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public int getHeight() {
return parent.getHeight();
}
@Override
public int getMinBuildHeight() {
return parent.getMinBuildHeight();
}
@Override
public int getSectionsCount() {
return parent.getSectionsCount();
}
@Override
public int getMinSection() {
return parent.getMinSection();
}
@Override
public int getMaxSection() {
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) {
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i) {
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i) {
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i) {
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i) {
return parent.getSectionYFromSectionIndex(i);
}
}
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
int i = smoothingRange;
if (i == 0)
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
int j = (i * 2 + 1) * (i * 2 + 1);
int k = 0;
int l = 0;
int m = 0;
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
while (cursor3D.advance())
{
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
int n;
if (LodCommonMain.forgeMethodCaller != null)
{
n = LodCommonMain.forgeMethodCaller.colorResolverGetColor(colorResolver, _getBiome(mutableBlockPos),
mutableBlockPos.getX(), mutableBlockPos.getZ());
}
else
{
n = colorResolver.getColor(_getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
}
k += (n & 0xFF0000) >> 16;
l += (n & 0xFF00) >> 8;
m += n & 0xFF;
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
return calculateBlockTint(blockPos, colorResolver);
}
@Override
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
@Override
public LevelLightEngine getLightEngine()
{
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos)
{
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i)
{
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos)
{
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos)
{
return parent.getBlockEntity(blockPos);
}
@Override
public BlockState getBlockState(BlockPos blockPos)
{
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos)
{
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos)
{
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel()
{
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB)
{
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult clip(ClipContext clipContext)
{
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState)
{
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier)
{
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos)
{
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getMaxBuildHeight()
{
return parent.getMaxBuildHeight();
}
#if POST_MC_1_17_1
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType)
{
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext)
{
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public int getHeight()
{
return parent.getHeight();
}
@Override
public int getMinBuildHeight()
{
return parent.getMinBuildHeight();
}
@Override
public int getSectionsCount()
{
return parent.getSectionsCount();
}
@Override
public int getMinSection()
{
return parent.getMinSection();
}
@Override
public int getMaxSection()
{
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos)
{
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i)
{
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i)
{
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i)
{
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i)
{
return parent.getSectionYFromSectionIndex(i);
}
#endif
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.block;
import net.minecraft.core.BlockPos;
@@ -33,57 +33,68 @@ import org.jetbrains.annotations.Nullable;
import net.minecraft.core.Holder;
#endif
public class TintWithoutLevelOverrider implements BlockAndTintGetter {
final BiomeWrapper biome;
public TintWithoutLevelOverrider(BiomeWrapper biome) {
this.biome = biome;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
return colorResolver.getColor(_unwrap(biome.biome), blockPos.getX(), blockPos.getZ());
}
private Biome _unwrap(#if POST_MC_1_18_2 Holder<Biome> #else Biome #endif biome) {
public class TintWithoutLevelOverrider implements BlockAndTintGetter
{
final BiomeWrapper biome;
public TintWithoutLevelOverrider(BiomeWrapper biome)
{
this.biome = biome;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
return colorResolver.getColor(_unwrap(biome.biome), blockPos.getX(), blockPos.getZ());
}
private Biome _unwrap(#if POST_MC_1_18_2 Holder<Biome> #else Biome #endif biome)
{
#if POST_MC_1_18_2
return biome.value();
return biome.value();
#else
return biome;
return biome;
#endif
}
@Override
public float getShade(Direction direction, boolean shade) {
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public LevelLightEngine getLightEngine() {
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public BlockState getBlockState(BlockPos pos) {
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public FluidState getFluidState(BlockPos pos) {
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
}
@Override
public float getShade(Direction direction, boolean shade)
{
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public LevelLightEngine getLightEngine()
{
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public BlockState getBlockState(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public FluidState getFluidState(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
#if MC_1_17_1 || POST_MC_1_18_2
@Override
public int getHeight() {
throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public int getMinBuildHeight() {
throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public int getHeight()
{
throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public int getMinBuildHeight()
{
throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
#endif
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.block;
import net.minecraft.core.BlockPos;
@@ -34,25 +34,29 @@ import org.jetbrains.annotations.Nullable;
import net.minecraft.core.Holder;
#endif
public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter {
final BiomeWrapper biome;
public int smoothingRange;
public TintWithoutLevelSmoothOverrider(BiomeWrapper biome, int smoothingRange) {
this.biome = biome;
this.smoothingRange = smoothingRange;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
return colorResolver.getColor(_unwrap(biome.biome), blockPos.getX(), blockPos.getZ());
}
private Biome _unwrap(#if POST_MC_1_18_2 Holder<Biome> #else Biome #endif biome) {
public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter
{
final BiomeWrapper biome;
public int smoothingRange;
public TintWithoutLevelSmoothOverrider(BiomeWrapper biome, int smoothingRange)
{
this.biome = biome;
this.smoothingRange = smoothingRange;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
return colorResolver.getColor(_unwrap(biome.biome), blockPos.getX(), blockPos.getZ());
}
private Biome _unwrap(#if POST_MC_1_18_2 Holder<Biome> #else Biome #endif biome)
{
#if POST_MC_1_18_2
return biome.value();
return biome.value();
#else
return biome;
return biome;
#endif
}
}
//
// public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
// {
@@ -82,40 +86,47 @@ public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter {
// }
// return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
// }
@Override
public float getShade(Direction direction, boolean shade) {
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public LevelLightEngine getLightEngine() {
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public BlockState getBlockState(BlockPos pos) {
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public FluidState getFluidState(BlockPos pos) {
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public float getShade(Direction direction, boolean shade)
{
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public LevelLightEngine getLightEngine()
{
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public BlockState getBlockState(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public FluidState getFluidState(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
#if MC_1_17_1 || POST_MC_1_18_2
@Override
public int getHeight() {
throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public int getMinBuildHeight() {
throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public int getHeight()
{
throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
@Override
public int getMinBuildHeight()
{
throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
#endif
}
@@ -7,19 +7,23 @@ import net.minecraft.world.level.block.state.BlockState;
import java.util.concurrent.ConcurrentHashMap;
public class ClientBlockDetailMap {
private final ConcurrentHashMap<BlockState, ClientBlockStateCache> blockCache = new ConcurrentHashMap<>();
//private final ConcurrentHashMap<#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif, Biome> biomeMap = new ConcurrentHashMap<>();
private final ClientLevelWrapper level;
public ClientBlockDetailMap(ClientLevelWrapper level) { this.level = level; }
public ClientBlockStateCache getBlockStateData(BlockState state, DhBlockPos pos) { //TODO: Allow a per pos unique setting
return blockCache.computeIfAbsent(state, (s) -> new ClientBlockStateCache(s, level, new DhBlockPos(0,0,0)));
}
public void clear() { blockCache.clear(); }
public int getColor(BlockState state, BiomeWrapper biome, DhBlockPos pos) {
return getBlockStateData(state, pos).getAndResolveFaceColor(biome);
}
public class ClientBlockDetailMap
{
private final ConcurrentHashMap<BlockState, ClientBlockStateCache> blockCache = new ConcurrentHashMap<>();
//private final ConcurrentHashMap<#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif, Biome> biomeMap = new ConcurrentHashMap<>();
private final ClientLevelWrapper level;
public ClientBlockDetailMap(ClientLevelWrapper level) { this.level = level; }
public ClientBlockStateCache getBlockStateData(BlockState state, DhBlockPos pos)
{ //TODO: Allow a per pos unique setting
return blockCache.computeIfAbsent(state, (s) -> new ClientBlockStateCache(s, level, new DhBlockPos(0, 0, 0)));
}
public void clear() { blockCache.clear(); }
public int getColor(BlockState state, BiomeWrapper biome, DhBlockPos pos)
{
return getBlockStateData(state, pos).getAndResolveFaceColor(biome);
}
}
@@ -29,178 +29,196 @@ import java.util.List;
import java.util.Random;
/**
*
* @version 2022-9-16
*/
public class ClientBlockStateCache
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
#if PRE_MC_1_19_2
public static final Random random = new Random(0);
public static final Random random = new Random(0);
#else
public static final RandomSource random = RandomSource.create();
public static final RandomSource random = RandomSource.create();
#endif
public final BlockState state;
public final LevelReader level;
public final BlockPos pos;
public ClientBlockStateCache(BlockState blockState, IClientLevelWrapper samplingLevel, DhBlockPos samplingPos) {
state = blockState;
level = (LevelReader) samplingLevel.getWrappedMcObject();
pos = McObjectConverter.Convert(samplingPos);
resolveColors();
//LOGGER.info("ClientBlocKCache created for {}", blockState);
}
boolean isColorResolved = false;
int baseColor = 0; //TODO: Impl per-face color
boolean needShade = true;
boolean needPostTinting = false;
int tintIndex = 0;
public static final int FLOWER_COLOR_SCALE = 5;
enum ColorMode {
Default,
Flower,
Leaves;
static ColorMode getColorMode(Block b) {
if (b instanceof LeavesBlock) return Leaves;
if (b instanceof FlowerBlock) return Flower;
return Default;
}
}
private static int getWidth(TextureAtlasSprite texture) {
public final BlockState state;
public final LevelReader level;
public final BlockPos pos;
public ClientBlockStateCache(BlockState blockState, IClientLevelWrapper samplingLevel, DhBlockPos samplingPos)
{
state = blockState;
level = (LevelReader) samplingLevel.getWrappedMcObject();
pos = McObjectConverter.Convert(samplingPos);
resolveColors();
//LOGGER.info("ClientBlocKCache created for {}", blockState);
}
boolean isColorResolved = false;
int baseColor = 0; //TODO: Impl per-face color
boolean needShade = true;
boolean needPostTinting = false;
int tintIndex = 0;
public static final int FLOWER_COLOR_SCALE = 5;
enum ColorMode
{
Default,
Flower,
Leaves;
static ColorMode getColorMode(Block b)
{
if (b instanceof LeavesBlock) return Leaves;
if (b instanceof FlowerBlock) return Flower;
return Default;
}
}
private static int getWidth(TextureAtlasSprite texture)
{
#if PRE_MC_1_19_4
return texture.getWidth();
return texture.getWidth();
#else
return texture.contents().width();
return texture.contents().width();
#endif
}
private static int getHeight(TextureAtlasSprite texture) {
}
private static int getHeight(TextureAtlasSprite texture)
{
#if PRE_MC_1_19_4
return texture.getHeight();
return texture.getHeight();
#else
return texture.contents().height();
return texture.contents().height();
#endif
}
//TODO: Perhaps make this not just use the first frame?
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode) {
int count = 0;
double alpha = 0;
double red = 0;
double green = 0;
double blue = 0;
int tempColor;
{
// textures normally use u and v instead of x and y
for (int u = 0; u < getWidth(texture); u++)
{
for (int v = 0; v < getHeight(texture); v++)
{
//note: Minecraft color format is: 0xAA BB GG RR
//________ DH mod color format is: 0xAA RR GG BB
//OpenGL RGBA format native order: 0xRR GG BB AA
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
double r = ((tempColor & 0x000000FF) )/255.;
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
int scale = 1;
if (colorMode == ColorMode.Leaves) {
r *= a;
g *= a;
b *= a;
a = 1.;
} else if (a==0.) {
continue;
} else if (colorMode == ColorMode.Flower && (g+0.1<b || g+0.1<r)) {
scale = FLOWER_COLOR_SCALE;
}
count += scale;
alpha += a*a*scale;
red += r*r*scale;
green += g*g*scale;
blue += b*b*scale;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = ColorUtil.rgbToInt(0,255,255,255);
else
{
// determine the average color
tempColor = ColorUtil.rgbToInt(
(int) (Math.sqrt(alpha/count)*255.),
(int) (Math.sqrt(red / count)*255.),
(int) (Math.sqrt(green / count)*255.),
(int) (Math.sqrt(blue / count)*255.));
}
return tempColor;
}
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
private void resolveColors() {
if (isColorResolved) return;
if (state.getFluidState().isEmpty()) {
List<BakedQuad> quads = null;
for (Direction direction : DIRECTION_ORDER)
{
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, direction, random);
if (quads != null && !quads.isEmpty() &&
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
break;
};
if (quads == null || quads.isEmpty()) {
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, null, random);
}
if (quads != null && !quads.isEmpty()) {
needPostTinting = quads.get(0).isTinted();
needShade = quads.get(0).isShade();
tintIndex = quads.get(0).getTintIndex();
baseColor = calculateColorFromTexture(
}
//TODO: Perhaps make this not just use the first frame?
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode)
{
int count = 0;
double alpha = 0;
double red = 0;
double green = 0;
double blue = 0;
int tempColor;
{
// textures normally use u and v instead of x and y
for (int u = 0; u < getWidth(texture); u++)
{
for (int v = 0; v < getHeight(texture); v++)
{
//note: Minecraft color format is: 0xAA BB GG RR
//________ DH mod color format is: 0xAA RR GG BB
//OpenGL RGBA format native order: 0xRR GG BB AA
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
double r = ((tempColor & 0x000000FF)) / 255.;
double g = ((tempColor & 0x0000FF00) >>> 8) / 255.;
double b = ((tempColor & 0x00FF0000) >>> 16) / 255.;
double a = ((tempColor & 0xFF000000) >>> 24) / 255.;
int scale = 1;
if (colorMode == ColorMode.Leaves)
{
r *= a;
g *= a;
b *= a;
a = 1.;
}
else if (a == 0.)
{
continue;
}
else if (colorMode == ColorMode.Flower && (g + 0.1 < b || g + 0.1 < r))
{
scale = FLOWER_COLOR_SCALE;
}
count += scale;
alpha += a * a * scale;
red += r * r * scale;
green += g * g * scale;
blue += b * b * scale;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = ColorUtil.rgbToInt(0, 255, 255, 255);
else
{
// determine the average color
tempColor = ColorUtil.rgbToInt(
(int) (Math.sqrt(alpha / count) * 255.),
(int) (Math.sqrt(red / count) * 255.),
(int) (Math.sqrt(green / count) * 255.),
(int) (Math.sqrt(blue / count) * 255.));
}
return tempColor;
}
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
private void resolveColors()
{
if (isColorResolved) return;
if (state.getFluidState().isEmpty())
{
List<BakedQuad> quads = null;
for (Direction direction : DIRECTION_ORDER)
{
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, direction, random);
if (quads != null && !quads.isEmpty() &&
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
break;
} ;
if (quads == null || quads.isEmpty())
{
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, null, random);
}
if (quads != null && !quads.isEmpty())
{
needPostTinting = quads.get(0).isTinted();
needShade = quads.get(0).isShade();
tintIndex = quads.get(0).getTintIndex();
baseColor = calculateColorFromTexture(
#if PRE_MC_1_17_1 quads.get(0).sprite,
#else quads.get(0).getSprite(), #endif
ColorMode.getColorMode(state.getBlock()));
} else { // Backup method.
needPostTinting = false;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
} else { // Liquid Block
needPostTinting = true;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
isColorResolved = true;
}
public int getAndResolveFaceColor(BiomeWrapper biome)
{
// FIXME: impl per-face colors
if (!needPostTinting) return baseColor;
int tintColor = Minecraft.getInstance().getBlockColors()
.getColor(state, new TintWithoutLevelOverrider(biome), pos, tintIndex);
if (tintColor == -1) return baseColor;
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
}
ColorMode.getColorMode(state.getBlock()));
}
else
{ // Backup method.
needPostTinting = false;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
}
else
{ // Liquid Block
needPostTinting = true;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
isColorResolved = true;
}
public int getAndResolveFaceColor(BiomeWrapper biome)
{
// FIXME: impl per-face colors
if (!needPostTinting) return baseColor;
int tintColor = Minecraft.getInstance().getBlockColors()
.getColor(state, new TintWithoutLevelOverrider(biome), pos, tintIndex);
if (tintColor == -1) return baseColor;
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.block.cache;
import java.util.concurrent.ConcurrentHashMap;
@@ -32,10 +32,12 @@ public class ServerBlockDetailMap
//private final ConcurrentHashMap<#if PRE_MC_1_18_2 Biome #else Holder<Biome> #endif, Biome> biomeMap = new ConcurrentHashMap<>();
private final ServerLevelWrapper level;
public ServerBlockDetailMap(ServerLevelWrapper level) { this.level = level; }
public ServerBlockStateCache getBlockStateData(BlockState state, DhBlockPos pos) { //TODO: Allow a per pos unique setting
return blockCache.computeIfAbsent(state, (s) -> new ServerBlockStateCache(s, level, new DhBlockPos(0,0,0)));
public ServerBlockStateCache getBlockStateData(BlockState state, DhBlockPos pos)
{ //TODO: Allow a per pos unique setting
return blockCache.computeIfAbsent(state, (s) -> new ServerBlockStateCache(s, level, new DhBlockPos(0, 0, 0)));
}
public void clear() { blockCache.clear(); }
}
@@ -15,63 +15,71 @@ import org.apache.logging.log4j.Logger;
import java.util.Arrays;
/**
*
* @version 2022-9-16
*/
public class ServerBlockStateCache
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public final BlockState state;
public final LevelReader level;
public final BlockPos pos;
public ServerBlockStateCache(BlockState blockState, ILevelWrapper samplingLevel, DhBlockPos samplingPos) {
state = blockState;
level = (LevelReader) samplingLevel.getWrappedMcObject();
pos = McObjectConverter.Convert(samplingPos);
resolveShapes();
//LOGGER.info("ServerBlockState created for {}", blockState);
}
boolean noCollision = false;
boolean[] occludeFaces = null;
boolean[] fullFaces = null;
boolean isShapeResolved = false;
public void resolveShapes() {
if (isShapeResolved) return;
if (state.getFluidState().isEmpty()) {
noCollision = state.getCollisionShape(level, pos).isEmpty();
occludeFaces = new boolean[6];
if (state.canOcclude()) {
for (Direction dir : Direction.values()) {
// Note: isEmpty() isn't quite correct... best would be a isFull() or something...
occludeFaces[McObjectConverter.Convert(dir).ordinal()]
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public final BlockState state;
public final LevelReader level;
public final BlockPos pos;
public ServerBlockStateCache(BlockState blockState, ILevelWrapper samplingLevel, DhBlockPos samplingPos)
{
state = blockState;
level = (LevelReader) samplingLevel.getWrappedMcObject();
pos = McObjectConverter.Convert(samplingPos);
resolveShapes();
//LOGGER.info("ServerBlockState created for {}", blockState);
}
boolean noCollision = false;
boolean[] occludeFaces = null;
boolean[] fullFaces = null;
boolean isShapeResolved = false;
public void resolveShapes()
{
if (isShapeResolved) return;
if (state.getFluidState().isEmpty())
{
noCollision = state.getCollisionShape(level, pos).isEmpty();
occludeFaces = new boolean[6];
if (state.canOcclude())
{
for (Direction dir : Direction.values())
{
// Note: isEmpty() isn't quite correct... best would be a isFull() or something...
occludeFaces[McObjectConverter.Convert(dir).ordinal()]
= !state.getFaceOcclusionShape(level, pos, dir).isEmpty();
}
}
VoxelShape voxelShape = state.getShape(level, pos);
fullFaces = new boolean[6];
if (!voxelShape.isEmpty()) {
for (Direction dir : Direction.values()) {
VoxelShape faceShape = voxelShape.getFaceShape(dir);
AABB aabb = faceShape.bounds();
boolean xFull = aabb.minX <= 0.01 && aabb.maxX >= 0.99;
boolean yFull = aabb.minY <= 0.01 && aabb.maxY >= 0.99;
boolean zFull = aabb.minZ <= 0.01 && aabb.maxZ >= 0.99;
fullFaces[McObjectConverter.Convert(dir).ordinal()] =
(xFull || dir.getAxis().equals(Direction.Axis.X))
&& (yFull || dir.getAxis().equals(Direction.Axis.Y))
&& (zFull || dir.getAxis().equals(Direction.Axis.Z));
}
}
} else { // Liquid Block. Treat as full block
occludeFaces = new boolean[6];
Arrays.fill(occludeFaces, true);
fullFaces = new boolean[6];
Arrays.fill(fullFaces, true);
}
}
}
VoxelShape voxelShape = state.getShape(level, pos);
fullFaces = new boolean[6];
if (!voxelShape.isEmpty())
{
for (Direction dir : Direction.values())
{
VoxelShape faceShape = voxelShape.getFaceShape(dir);
AABB aabb = faceShape.bounds();
boolean xFull = aabb.minX <= 0.01 && aabb.maxX >= 0.99;
boolean yFull = aabb.minY <= 0.01 && aabb.maxY >= 0.99;
boolean zFull = aabb.minZ <= 0.01 && aabb.maxZ >= 0.99;
fullFaces[McObjectConverter.Convert(dir).ordinal()] =
(xFull || dir.getAxis().equals(Direction.Axis.X))
&& (yFull || dir.getAxis().equals(Direction.Axis.Y))
&& (zFull || dir.getAxis().equals(Direction.Axis.Z));
}
}
}
else
{ // Liquid Block. Treat as full block
occludeFaces = new boolean[6];
Arrays.fill(occludeFaces, true);
fullFaces = new boolean[6];
Arrays.fill(fullFaces, true);
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.chunk;
import com.seibel.distanthorizons.api.enums.config.ELightGenerationMode;
@@ -78,7 +78,7 @@ public class ChunkWrapper implements IChunkWrapper
* just before the light engine is ticked, (right after all light changes is marked to the engine to be processed).
* To fix this, on client-only mode, we mixin-redirect the `isClientLightReady()` so that after the call, it will
* trigger a synchronous update of this flag here on all chunks that are wrapped. <br><br>
*
*
* Note: Using a static weak hash map to store the chunks that need to be updated, as instance of chunk wrapper
* can be duplicated, with same chunk instance. And the data stored here are all temporary, and thus will not be
* visible when a chunk is re-wrapped later. <br>
@@ -169,10 +169,10 @@ public class ChunkWrapper implements IChunkWrapper
QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)));
#endif
}
@Override
public DhChunkPos getChunkPos() { return this.chunkPos; }
public ChunkAccess getChunk() { return this.chunk; }
@Override
@@ -217,29 +217,29 @@ public class ChunkWrapper implements IChunkWrapper
weakMapLock.readLock().unlock();
return fixedIsClientLightReady;
}
// called when in single player or in dedicated server, and the chunk is a level chunk (active)
return this.chunk.isLightCorrect() && levelChunk.loaded;
}
else
{
// called when in a single player world and the chunk is a proto chunk (in world gen, and not active)
return this.chunk.isLightCorrect();
return this.chunk.isLightCorrect();
}
#endif
}
@Override
public int getDhBlockLight(int relX, int y, int relZ)
public int getDhBlockLight(int relX, int y, int relZ)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
int index = this.relativeBlockPosToIndex(relX, y, relZ);
return this.blockLightArray[index];
return this.blockLightArray[index];
}
@Override
public void setDhBlockLight(int relX, int y, int relZ, int lightValue)
public void setDhBlockLight(int relX, int y, int relZ, int lightValue)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
@@ -248,7 +248,7 @@ public class ChunkWrapper implements IChunkWrapper
}
@Override
public int getDhSkyLight(int relX, int y, int relZ)
public int getDhSkyLight(int relX, int y, int relZ)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
@@ -256,7 +256,7 @@ public class ChunkWrapper implements IChunkWrapper
return this.skyLightArray[index];
}
@Override
public void setDhSkyLight(int relX, int y, int relZ, int lightValue)
public void setDhSkyLight(int relX, int y, int relZ, int lightValue)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, y, relZ);
@@ -282,7 +282,7 @@ public class ChunkWrapper implements IChunkWrapper
// note: this returns 0 if the chunk is unload
// MC lighting method
return this.lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(relX +this.getMinBlockX(), y, relZ +this.getMinBlockZ()));
return this.lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(relX + this.getMinBlockX(), y, relZ + this.getMinBlockZ()));
}
}
@@ -301,11 +301,11 @@ public class ChunkWrapper implements IChunkWrapper
else
{
// MC lighting method
return this.lightSource.getBrightness(LightLayer.SKY, new BlockPos(relX +this.getMinBlockX(), y, relZ +this.getMinBlockZ()));
return this.lightSource.getBrightness(LightLayer.SKY, new BlockPos(relX + this.getMinBlockX(), y, relZ + this.getMinBlockZ()));
}
}
@Override
@Override
public List<DhBlockPos> getBlockLightPosList()
{
// only populate the list once
@@ -315,12 +315,12 @@ public class ChunkWrapper implements IChunkWrapper
#if PRE_MC_1_20_1
this.chunk.getLights().forEach((blockPos) ->
this.chunk.getLights().forEach((blockPos) ->
{
this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
});
#elif MC_1_20_1
this.chunk.findBlockLightSources((blockPos, blockState) ->
this.chunk.findBlockLightSources((blockPos, blockState) ->
{
this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
});
@@ -357,49 +357,52 @@ public class ChunkWrapper implements IChunkWrapper
}
public LevelReader getColorResolver() { return this.lightSource; }
@Override
public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); }
@Override
public IBlockStateWrapper getBlockState(int relX, int relY, int relZ)
{
//if (wrappedLevel != null) return wrappedLevel.getBlockState(new DhBlockPos(x + getMinX(), y, z + getMinZ()));
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(new BlockPos(relX, relY, relZ)));
}
@Override
public boolean isStillValid() { return this.wrappedLevel == null || this.wrappedLevel.tryGetChunk(this.chunkPos) == this; }
#if POST_MC_1_20_1
private static boolean checkLightSectionsOnChunk(LevelChunk chunk, LevelLightEngine engine) {
private static boolean checkLightSectionsOnChunk(LevelChunk chunk, LevelLightEngine engine)
{
LevelChunkSection[] sections = chunk.getSections();
int minY = chunk.getMinSection();
int maxY = chunk.getMaxSection();
for (int y = minY; y < maxY; ++y) {
for (int y = minY; y < maxY; ++y)
{
LevelChunkSection section = sections[chunk.getSectionIndexFromSectionY(y)];
if (section.hasOnlyAir()) continue;
if (!engine.lightOnInSection(SectionPos.of(chunk.getPos(), y))) {
if (!engine.lightOnInSection(SectionPos.of(chunk.getPos(), y)))
{
return false;
}
}
return true;
}
#endif
// Should be called after client light updates are triggered.
private static boolean updateClientLightReady(ChunkAccess chunk, boolean oldValue)
{
if (chunk instanceof LevelChunk && ((LevelChunk)chunk).getLevel() instanceof ClientLevel)
if (chunk instanceof LevelChunk && ((LevelChunk) chunk).getLevel() instanceof ClientLevel)
{
LevelChunk levelChunk = (LevelChunk)chunk;
ClientChunkCache clientChunkCache = ((ClientLevel)levelChunk.getLevel()).getChunkSource();
LevelChunk levelChunk = (LevelChunk) chunk;
ClientChunkCache clientChunkCache = ((ClientLevel) levelChunk.getLevel()).getChunkSource();
return clientChunkCache.getChunkForLighting(chunk.getPos().x, chunk.getPos().z) != null &&
#if MC_1_16_5 || MC_1_17_1
levelChunk.isLightCorrect();
#elif PRE_MC_1_20_1
#elif PRE_MC_1_20_1
levelChunk.isClientLightReady();
#else
#else
checkLightSectionsOnChunk(levelChunk, levelChunk.getLevel().getLightEngine());
#endif
}
@@ -408,7 +411,7 @@ public class ChunkWrapper implements IChunkWrapper
return oldValue;
}
}
public static void syncedUpdateClientLightStatus()
{
#if PRE_MC_1_18_2
@@ -419,7 +422,7 @@ public class ChunkWrapper implements IChunkWrapper
{
chunksToUpdateClientLightReady.replaceAll(ChunkWrapper::updateClientLightReady);
}
finally
finally
{
weakMapLock.writeLock().unlock();
}
@@ -436,16 +439,16 @@ public class ChunkWrapper implements IChunkWrapper
private void throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(int x, int y, int z) throws IndexOutOfBoundsException
{
// FIXME +/-1 is to handle the fact that LodDataBuilder adds +1 to all block lighting calculations, also done in the relative position validator
int minHeight = this.getMinBuildHeight()-1;
int maxHeight = this.getMaxBuildHeight()+1;
int minHeight = this.getMinBuildHeight() - 1;
int maxHeight = this.getMaxBuildHeight() + 1;
if (x < 0 || x >= LodUtil.CHUNK_WIDTH
|| z < 0 || z >= LodUtil.CHUNK_WIDTH
|| y < minHeight || y > maxHeight)
|| z < 0 || z >= LodUtil.CHUNK_WIDTH
|| y < minHeight || y > maxHeight)
{
String errorMessage = "Relative position ["+x+","+y+","+z+"] out of bounds. \n" +
String errorMessage = "Relative position [" + x + "," + y + "," + z + "] out of bounds. \n" +
"X/Z must be between 0 and 15 (inclusive) \n" +
"Y must be between ["+minHeight+"] and ["+maxHeight+"] (inclusive).";
"Y must be between [" + minHeight + "] and [" + maxHeight + "] (inclusive).";
throw new IndexOutOfBoundsException(errorMessage);
}
}
@@ -455,21 +458,21 @@ public class ChunkWrapper implements IChunkWrapper
* Converts a 3D position into a 1D array index. <br><br>
*
* Source: <br>
* <a href="https://stackoverflow.com/questions/7367770/how-to-flatten-or-index-3d-array-in-1d-array">stackoverflow</a>
* <a href="https://stackoverflow.com/questions/7367770/how-to-flatten-or-index-3d-array-in-1d-array">stackoverflow</a>
*/
public int relativeBlockPosToIndex(int xRel, int y, int zRel)
public int relativeBlockPosToIndex(int xRel, int y, int zRel)
{
int yRel = y - this.getMinBuildHeight();
return (zRel * LodUtil.CHUNK_WIDTH * this.getHeight()) + (yRel * LodUtil.CHUNK_WIDTH) + xRel;
return (zRel * LodUtil.CHUNK_WIDTH * this.getHeight()) + (yRel * LodUtil.CHUNK_WIDTH) + xRel;
}
/**
* Converts a 3D position into a 1D array index. <br><br>
*
* Source: <br>
* <a href="https://stackoverflow.com/questions/7367770/how-to-flatten-or-index-3d-array-in-1d-array">stackoverflow</a>
* <a href="https://stackoverflow.com/questions/7367770/how-to-flatten-or-index-3d-array-in-1d-array">stackoverflow</a>
*/
public DhBlockPos indexToRelativeBlockPos(int index)
public DhBlockPos indexToRelativeBlockPos(int index)
{
final int zRel = index / (LodUtil.CHUNK_WIDTH * this.getHeight());
index -= (zRel * LodUtil.CHUNK_WIDTH * this.getHeight());
@@ -47,7 +47,7 @@ import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.client.resources.language.I18n; // translation
import net.minecraft.client.resources.language.I18n; // translation
#if POST_MC_1_17_1
import net.minecraft.client.gui.narration.NarratableEntry;
#endif
@@ -68,6 +68,7 @@ import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
* @version 5-21-2022
*/
// FLOATS DONT WORK WITH THIS
/** This file is going to be removed sometime soon, please dont hook onto anything within this file until the new UI is compleated */
@SuppressWarnings("unchecked")
public class ClassicConfigGUI
@@ -78,338 +79,388 @@ public class ClassicConfigGUI
private static final Logger LOGGER = LogManager.getLogger();
//==============//
// Initializers //
//==============//
// Some regexes to check if an input is valid
private static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)");
private static final Pattern DECIMAL_ONLY_REGEX = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
private static class ConfigScreenConfigs {
// This contains all the configs for the configs
public static final int SpaceFromRightScreen = 10;
public static final int ButtonWidthSpacing = 5;
public static final int ResetButtonWidth = 40;
}
/**
* The terribly coded old stuff
*/
public static class EntryInfo {
Object widget;
Map.Entry<EditBox, Component> error;
String tempValue;
int index;
}
/**
* creates a text field
*/
private static void textField(AbstractConfigType info, Function<String, Number> func, Pattern pattern, boolean cast) {
boolean isNumber = pattern != null;
((EntryInfo) info.guiValue).widget = (BiFunction<EditBox, Button, Predicate<String>>) (editBox, button) -> stringValue ->
{
stringValue = stringValue.trim();
if (!(stringValue.isEmpty() || !isNumber || pattern.matcher(stringValue).matches()))
return false;
Number value = 0;
((EntryInfo) info.guiValue).error = null;
if (isNumber && !stringValue.isEmpty() && !stringValue.equals("-") && !stringValue.equals(".")) {
try {
value = func.apply(stringValue);
} catch (Exception e) {
value = null;
}
byte isValid = ((ConfigEntry) info).isValid(value);
switch (isValid) {
case 0: ((EntryInfo) info.guiValue).error = null; break;
case -1: ((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry) info).getMin())); break;
case 1: ((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry) info).getMax())); break;
case 2: ((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid")); break;
}
}
((EntryInfo) info.guiValue).tempValue = stringValue;
editBox.setTextColor(((ConfigEntry) info).isValid(value) == 0 ? 0xFFFFFFFF : 0xFFFF7777);
//==============//
// Initializers //
//==============//
// Some regexes to check if an input is valid
private static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)");
private static final Pattern DECIMAL_ONLY_REGEX = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
private static class ConfigScreenConfigs
{
// This contains all the configs for the configs
public static final int SpaceFromRightScreen = 10;
public static final int ButtonWidthSpacing = 5;
public static final int ResetButtonWidth = 40;
}
/**
* The terribly coded old stuff
*/
public static class EntryInfo
{
Object widget;
Map.Entry<EditBox, Component> error;
String tempValue;
int index;
}
/**
* creates a text field
*/
private static void textField(AbstractConfigType info, Function<String, Number> func, Pattern pattern, boolean cast)
{
boolean isNumber = pattern != null;
((EntryInfo) info.guiValue).widget = (BiFunction<EditBox, Button, Predicate<String>>) (editBox, button) -> stringValue ->
{
stringValue = stringValue.trim();
if (!(stringValue.isEmpty() || !isNumber || pattern.matcher(stringValue).matches()))
return false;
Number value = 0;
((EntryInfo) info.guiValue).error = null;
if (isNumber && !stringValue.isEmpty() && !stringValue.equals("-") && !stringValue.equals("."))
{
try
{
value = func.apply(stringValue);
}
catch (Exception e)
{
value = null;
}
byte isValid = ((ConfigEntry) info).isValid(value);
switch (isValid)
{
case 0:
((EntryInfo) info.guiValue).error = null; break;
case -1:
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry) info).getMin())); break;
case 1:
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry) info).getMax())); break;
case 2:
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid")); break;
}
}
((EntryInfo) info.guiValue).tempValue = stringValue;
editBox.setTextColor(((ConfigEntry) info).isValid(value) == 0 ? 0xFFFFFFFF : 0xFFFF7777);
// button.active = entries.stream().allMatch(e -> e.inLimits);
if (((ConfigEntry) info).isValid(value) == 0 && info.getType() != List.class) {
if (!cast)
((ConfigEntry) info).setWithoutSaving(value);
else
((ConfigEntry) info).setWithoutSaving(value.intValue());
}
if (((ConfigEntry) info).isValid(value) == 0 && info.getType() != List.class)
{
if (!cast)
((ConfigEntry) info).setWithoutSaving(value);
else
((ConfigEntry) info).setWithoutSaving(value.intValue());
}
// else if (((ConfigEntry) info).isValidMemoryAddress() == 0)
// {
// if (((List<String>) info.get()).size() == ((EntryInfo) info.guiValue).index)
// info.set(((List<String>) info.get()).add(""));
// info.set(((List<String>) info.get()).set(((EntryInfo) info.guiValue).index, Arrays.stream(((EntryInfo) info.guiValue).tempValue.replace("[", "").replace("]", "").split(", ")).collect(Collectors.toList()).get(0)));
// }
return true;
};
}
//==============//
// GUI handling //
//==============//
/**
* if you want to get this config gui's screen call this
*/
public static Screen getScreen(ConfigBase configBase, Screen parent, String category) {
return new ConfigScreen(configBase, parent, category);
}
/**
* Pain
*/
private static class ConfigScreen extends DhScreen {
protected ConfigScreen(ConfigBase configBase, Screen parent, String category) {
super(Translatable(
I18n.exists(configBase.modID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ?
configBase.modID + ".config.title" :
configBase.modID + ".config" + (category.isEmpty() ? "" : "." + category) + ".title")
);
this.configBase = configBase;
this.parent = parent;
this.category = category;
this.translationPrefix = configBase.modID + ".config.";
}
private final ConfigBase configBase;
private final String translationPrefix;
private final Screen parent;
private final String category;
private ConfigListWidget list;
private boolean reload = false;
private Button doneButton;
// Real Time config update //
@Override
public void tick() {
super.tick();
}
/**
* When you close it, it goes to the previous screen and saves
*/
@Override
public void onClose() {
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
Objects.requireNonNull(minecraft).setScreen(this.parent);
}
@Override
protected void init() {
super.init();
if (!reload)
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
// Changelog button
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
return true;
};
}
//==============//
// GUI handling //
//==============//
/**
* if you want to get this config gui's screen call this
*/
public static Screen getScreen(ConfigBase configBase, Screen parent, String category)
{
return new ConfigScreen(configBase, parent, category);
}
/**
* Pain
*/
private static class ConfigScreen extends DhScreen
{
protected ConfigScreen(ConfigBase configBase, Screen parent, String category)
{
super(Translatable(
I18n.exists(configBase.modID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ?
configBase.modID + ".config.title" :
configBase.modID + ".config" + (category.isEmpty() ? "" : "." + category) + ".title")
);
this.configBase = configBase;
this.parent = parent;
this.category = category;
this.translationPrefix = configBase.modID + ".config.";
}
private final ConfigBase configBase;
private final String translationPrefix;
private final Screen parent;
private final String category;
private ConfigListWidget list;
private boolean reload = false;
private Button doneButton;
// Real Time config update //
@Override
public void tick()
{
super.tick();
}
/**
* When you close it, it goes to the previous screen and saves
*/
@Override
public void onClose()
{
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
Objects.requireNonNull(minecraft).setScreen(this.parent);
}
@Override
protected void init()
{
super.init();
if (!reload)
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
// Changelog button
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
{
this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen
this.width - 28, this.height - 28,
// Width and height of the button
20, 20,
// Offset
0, 0,
// Some textuary stuff
0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20,
// Create the button and tell it where to go
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this)),
// Add a title to the button
Translatable(ModInfo.ID + ".updater.title")
));
}
addBtn(MakeBtn(CommonComponents.GUI_CANCEL, this.width / 2 - 154, this.height - 28, 150, 20, button -> {
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
Objects.requireNonNull(minecraft).setScreen(parent);
}));
doneButton = addBtn(MakeBtn( CommonComponents.GUI_DONE,this.width / 2 + 4, this.height - 28, 150, 20, (button) -> {
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
Objects.requireNonNull(minecraft).setScreen(parent);
}));
this.list = new ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, this.height - 32, 25);
if (this.minecraft != null && this.minecraft.level != null)
this.list.setRenderBackground(false);
this.addWidget(this.list);
for (AbstractConfigType info : ConfigBase.INSTANCE.entries) {
try {
if (info.getCategory().matches(category) && info.getAppearance().showInGui)
addMenuItem(info);
} catch (Exception e) {
System.out.println("ERROR: Failed to show ["+info.getNameWCategory()+"]");
if (info.get() != null)
System.out.print(" with the value ["+info.get()+"] with type ["+info.getType()+"]");
e.printStackTrace();
}
}
}
private void addMenuItem(AbstractConfigType info) {
initEntry(info, this.translationPrefix);
Component name = Translatable(translationPrefix + info.getNameWCategory());
if (ConfigEntry.class.isAssignableFrom(info.getClass())) {
Button.OnPress btnAction = button -> {
((ConfigEntry) info).setWithoutSaving(((ConfigEntry) info).getDefaultValue());
((EntryInfo) info.guiValue).index = 0;
this.reload = true;
Objects.requireNonNull(minecraft).setScreen(this);
};
int a = this.width - ConfigScreenConfigs.SpaceFromRightScreen - 150 - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth;
int b = 0;
int c = ConfigScreenConfigs.ResetButtonWidth;
int d = 20;
Button resetButton = MakeBtn(TextOrLiteral("Reset") .withStyle(ChatFormatting.RED), a, b, c, d, btnAction);
if (((EntryInfo) info.guiValue).widget instanceof Map.Entry) {
Map.Entry<Button.OnPress, Function<Object, Component>> widget = (Map.Entry<Button.OnPress, Function<Object, Component>>) ((EntryInfo) info.guiValue).widget;
if (info.getType().isEnum()) {
widget.setValue(value -> Translatable(translationPrefix + "enum." + info.getType().getSimpleName() + "." + info.get().toString()));
}
this.list.addButton(MakeBtn(widget.getValue().apply(info.get()), this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen, 0, 150, 20, widget.getKey()), resetButton, null, name);
return;
} else if (((EntryInfo) info.guiValue).widget != null) {
EditBox widget = new EditBox(font, this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen + 2, 0, 150 - 4, 20, null);
widget.setMaxLength(150);
widget.insertText(String.valueOf(info.get()));
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) ((EntryInfo) info.guiValue).widget).apply(widget, doneButton);
widget.setFilter(processor);
this.list.addButton(widget, resetButton, null, name);
return;
}
}
if (ConfigCategory.class.isAssignableFrom(info.getClass())) {
Button widget = MakeBtn(name, this.width / 2 - 100, this.height - 28, 100 * 2, 20, (button -> {
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
Objects.requireNonNull(minecraft).setScreen(ClassicConfigGUI.getScreen(this.configBase, this, ((ConfigCategory) info).getDestination()));
}));
this.list.addButton(widget, null, null, null);
return;
}
if (ConfigUIButton.class.isAssignableFrom(info.getClass())) {
Button widget = MakeBtn(name, this.width / 2 - 100, this.height - 28, 100 * 2, 20, (button -> {
((ConfigUIButton) info).runAction();
}));
this.list.addButton(widget, null, null, null);
return;
}
if (ConfigUIComment.class.isAssignableFrom(info.getClass())) {
this.list.addButton(null, null, null, name);
return;
}
if (ConfigLinkedEntry.class.isAssignableFrom(info.getClass())) {
this.addMenuItem(((ConfigLinkedEntry) info).get());
return;
}
LOGGER.warn("Config ["+ info.getNameWCategory() +"] failed to show. Please try something like changing its type.");
}
@Override
this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen
this.width - 28, this.height - 28,
// Width and height of the button
20, 20,
// Offset
0, 0,
// Some textuary stuff
0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20,
// Create the button and tell it where to go
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this)),
// Add a title to the button
Translatable(ModInfo.ID + ".updater.title")
));
}
addBtn(MakeBtn(CommonComponents.GUI_CANCEL, this.width / 2 - 154, this.height - 28, 150, 20, button -> {
ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
Objects.requireNonNull(minecraft).setScreen(parent);
}));
doneButton = addBtn(MakeBtn(CommonComponents.GUI_DONE, this.width / 2 + 4, this.height - 28, 150, 20, (button) -> {
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
Objects.requireNonNull(minecraft).setScreen(parent);
}));
this.list = new ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, this.height - 32, 25);
if (this.minecraft != null && this.minecraft.level != null)
this.list.setRenderBackground(false);
this.addWidget(this.list);
for (AbstractConfigType info : ConfigBase.INSTANCE.entries)
{
try
{
if (info.getCategory().matches(category) && info.getAppearance().showInGui)
addMenuItem(info);
}
catch (Exception e)
{
System.out.println("ERROR: Failed to show [" + info.getNameWCategory() + "]");
if (info.get() != null)
System.out.print(" with the value [" + info.get() + "] with type [" + info.getType() + "]");
e.printStackTrace();
}
}
}
private void addMenuItem(AbstractConfigType info)
{
initEntry(info, this.translationPrefix);
Component name = Translatable(translationPrefix + info.getNameWCategory());
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
{
Button.OnPress btnAction = button -> {
((ConfigEntry) info).setWithoutSaving(((ConfigEntry) info).getDefaultValue());
((EntryInfo) info.guiValue).index = 0;
this.reload = true;
Objects.requireNonNull(minecraft).setScreen(this);
};
int a = this.width - ConfigScreenConfigs.SpaceFromRightScreen - 150 - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth;
int b = 0;
int c = ConfigScreenConfigs.ResetButtonWidth;
int d = 20;
Button resetButton = MakeBtn(TextOrLiteral("Reset").withStyle(ChatFormatting.RED), a, b, c, d, btnAction);
if (((EntryInfo) info.guiValue).widget instanceof Map.Entry)
{
Map.Entry<Button.OnPress, Function<Object, Component>> widget = (Map.Entry<Button.OnPress, Function<Object, Component>>) ((EntryInfo) info.guiValue).widget;
if (info.getType().isEnum())
{
widget.setValue(value -> Translatable(translationPrefix + "enum." + info.getType().getSimpleName() + "." + info.get().toString()));
}
this.list.addButton(MakeBtn(widget.getValue().apply(info.get()), this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen, 0, 150, 20, widget.getKey()), resetButton, null, name);
return;
}
else if (((EntryInfo) info.guiValue).widget != null)
{
EditBox widget = new EditBox(font, this.width - 150 - ConfigScreenConfigs.SpaceFromRightScreen + 2, 0, 150 - 4, 20, null);
widget.setMaxLength(150);
widget.insertText(String.valueOf(info.get()));
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) ((EntryInfo) info.guiValue).widget).apply(widget, doneButton);
widget.setFilter(processor);
this.list.addButton(widget, resetButton, null, name);
return;
}
}
if (ConfigCategory.class.isAssignableFrom(info.getClass()))
{
Button widget = MakeBtn(name, this.width / 2 - 100, this.height - 28, 100 * 2, 20, (button -> {
ConfigBase.INSTANCE.configFileINSTANCE.saveToFile();
Objects.requireNonNull(minecraft).setScreen(ClassicConfigGUI.getScreen(this.configBase, this, ((ConfigCategory) info).getDestination()));
}));
this.list.addButton(widget, null, null, null);
return;
}
if (ConfigUIButton.class.isAssignableFrom(info.getClass()))
{
Button widget = MakeBtn(name, this.width / 2 - 100, this.height - 28, 100 * 2, 20, (button -> {
((ConfigUIButton) info).runAction();
}));
this.list.addButton(widget, null, null, null);
return;
}
if (ConfigUIComment.class.isAssignableFrom(info.getClass()))
{
this.list.addButton(null, null, null, name);
return;
}
if (ConfigLinkedEntry.class.isAssignableFrom(info.getClass()))
{
this.addMenuItem(((ConfigLinkedEntry) info).get());
return;
}
LOGGER.warn("Config [" + info.getNameWCategory() + "] failed to show. Please try something like changing its type.");
}
@Override
#if PRE_MC_1_20_1
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
#else
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
#endif
{
this.renderBackground(matrices); // Renders background
this.list.render(matrices, mouseX, mouseY, delta); // Render buttons
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
// If the update is pending, display this message to inform the user that it will apply when the game restarts
if (SelfUpdater.deleteOldOnClose)
DhDrawString(matrices, font, Translatable(configBase.modID + ".updater.waitingForClose"), 4, height-38, 0xFFFFFF);
// Render the tooltip only if it can find a tooltip in the language file
for (AbstractConfigType info : ConfigBase.INSTANCE.entries) {
if (info.getCategory().matches(category) && info.getAppearance().showInGui) {
if (list.getHoveredButton(mouseX, mouseY).isPresent()) {
AbstractWidget buttonWidget = list.getHoveredButton(mouseX, mouseY).get();
Component text = ButtonEntry.buttonsWithText.get(buttonWidget);
// A quick fix for tooltips on linked entries
AbstractConfigType newInfo = ConfigLinkedEntry.class.isAssignableFrom(info.getClass())?
((ConfigLinkedEntry) info).get():
info;
Component name = Translatable(this.translationPrefix + (info.category.isEmpty() ? "" : info.category + ".") + info.getName());
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<Component> list = new ArrayList<>();
for (String str : I18n.get(key).split("\n")) {
list.add(TextOrTranslatable(str));
}
DhRenderComponentTooltip(matrices, font, list, mouseX, mouseY);
}
}
}
}
super.render(matrices, mouseX, mouseY, delta);
}
}
private static void initEntry(AbstractConfigType info, String translationPrefix) {
info.guiValue = new EntryInfo();
Class<?> fieldClass = info.getType();
if (ConfigEntry.class.isAssignableFrom(info.getClass())) {
if (fieldClass == Integer.class) {
// For int
textField(info, Integer::parseInt, INTEGER_ONLY_REGEX, true);
} else if (fieldClass == Double.class) {
// For double
textField(info, Double::parseDouble, DECIMAL_ONLY_REGEX, false);
} else if (fieldClass == String.class || fieldClass == List.class) {
// For string or list
textField(info, String::length, null, true);
} else if (fieldClass == Boolean.class) {
// For boolean
Function<Object, Component> func = value -> TextOrTranslatable((Boolean) value ? "True" : "False").withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
((EntryInfo) info.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
((ConfigEntry) info).setWithoutSaving(!(Boolean) info.get());
button.setMessage(func.apply(info.get()));
}, func);
}
else if (fieldClass.isEnum())
{
// For enum
List<?> values = Arrays.asList(info.getType().getEnumConstants());
Function<Object, Component> func = value -> Translatable(translationPrefix + "enum." + fieldClass.getSimpleName() + "." + info.get().toString());
((EntryInfo) info.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
{
this.renderBackground(matrices); // Renders background
this.list.render(matrices, mouseX, mouseY, delta); // Render buttons
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
// If the update is pending, display this message to inform the user that it will apply when the game restarts
if (SelfUpdater.deleteOldOnClose)
DhDrawString(matrices, font, Translatable(configBase.modID + ".updater.waitingForClose"), 4, height - 38, 0xFFFFFF);
// Render the tooltip only if it can find a tooltip in the language file
for (AbstractConfigType info : ConfigBase.INSTANCE.entries)
{
if (info.getCategory().matches(category) && info.getAppearance().showInGui)
{
if (list.getHoveredButton(mouseX, mouseY).isPresent())
{
AbstractWidget buttonWidget = list.getHoveredButton(mouseX, mouseY).get();
Component text = ButtonEntry.buttonsWithText.get(buttonWidget);
// A quick fix for tooltips on linked entries
AbstractConfigType newInfo = ConfigLinkedEntry.class.isAssignableFrom(info.getClass()) ?
((ConfigLinkedEntry) info).get() :
info;
Component name = Translatable(this.translationPrefix + (info.category.isEmpty() ? "" : info.category + ".") + info.getName());
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<Component> list = new ArrayList<>();
for (String str : I18n.get(key).split("\n"))
{
list.add(TextOrTranslatable(str));
}
DhRenderComponentTooltip(matrices, font, list, mouseX, mouseY);
}
}
}
}
super.render(matrices, mouseX, mouseY, delta);
}
}
private static void initEntry(AbstractConfigType info, String translationPrefix)
{
info.guiValue = new EntryInfo();
Class<?> fieldClass = info.getType();
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
{
if (fieldClass == Integer.class)
{
// For int
textField(info, Integer::parseInt, INTEGER_ONLY_REGEX, true);
}
else if (fieldClass == Double.class)
{
// For double
textField(info, Double::parseDouble, DECIMAL_ONLY_REGEX, false);
}
else if (fieldClass == String.class || fieldClass == List.class)
{
// For string or list
textField(info, String::length, null, true);
}
else if (fieldClass == Boolean.class)
{
// For boolean
Function<Object, Component> func = value -> TextOrTranslatable((Boolean) value ? "True" : "False").withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
((EntryInfo) info.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
((ConfigEntry) info).setWithoutSaving(!(Boolean) info.get());
button.setMessage(func.apply(info.get()));
}, func);
}
else if (fieldClass.isEnum())
{
// For enum
List<?> values = Arrays.asList(info.getType().getEnumConstants());
Function<Object, Component> func = value -> Translatable(translationPrefix + "enum." + fieldClass.getSimpleName() + "." + info.get().toString());
((EntryInfo) info.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
// get the currently selected enum and enum index
int startingIndex = values.indexOf(info.get());
Enum<?> enumValue = (Enum<?>) values.get(startingIndex);
// search for the next enum that is selectable
int index = startingIndex+1;
int index = startingIndex + 1;
index = (index >= values.size()) ? 0 : index;
while (index != startingIndex)
{
@@ -429,116 +480,135 @@ public class ClassicConfigGUI
{
// none of the enums should be selectable, this is a programmer error
enumValue = (Enum<?>) values.get(startingIndex);
LOGGER.warn("Enum ["+enumValue.getClass()+"] doesn't contain any values that should be selectable via the UI, sticking to the currently selected value ["+enumValue+"].");
LOGGER.warn("Enum [" + enumValue.getClass() + "] doesn't contain any values that should be selectable via the UI, sticking to the currently selected value [" + enumValue + "].");
}
info.set(enumValue);
button.setMessage(func.apply(info.get()));
}, func);
}
} else if (ConfigCategory.class.isAssignableFrom(info.getClass())) {
}
}
else if (ConfigCategory.class.isAssignableFrom(info.getClass()))
{
// if (!info.info.getName().equals(""))
// info.name = new TranslatableComponent(info.info.getName());
}
}
// return info;
}
public static class ConfigListWidget extends ContainerObjectSelectionList<ButtonEntry> {
Font textRenderer;
public ConfigListWidget(Minecraft minecraftClient, int i, int j, int k, int l, int m) {
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
textRenderer = minecraftClient.font;
}
public void addButton(AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text) {
this.addEntry(ButtonEntry.create(button, text, resetButton, indexButton));
}
@Override
public int getRowWidth() {
return 10000;
}
public Optional<AbstractWidget> getHoveredButton(double mouseX, double mouseY) {
for (ButtonEntry buttonEntry : this.children()) {
if (buttonEntry.button != null && buttonEntry.button.isMouseOver(mouseX, mouseY)) {
return Optional.of(buttonEntry.button);
}
}
return Optional.empty();
}
}
public static class ButtonEntry extends ContainerObjectSelectionList.Entry<ButtonEntry> {
private static final Font textRenderer = Minecraft.getInstance().font;
public final AbstractWidget button;
private final AbstractWidget resetButton;
private final AbstractWidget indexButton;
private final Component text;
private final List<AbstractWidget> children = new ArrayList<>();
public static final Map<AbstractWidget, Component> buttonsWithText = new HashMap<>();
private ButtonEntry(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) {
buttonsWithText.put(button, text);
this.button = button;
this.resetButton = resetButton;
this.text = text;
this.indexButton = indexButton;
if (button != null)
children.add(button);
if (resetButton != null)
children.add(resetButton);
if (indexButton != null)
children.add(indexButton);
}
public static ButtonEntry create(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) {
return new ButtonEntry(button, text, resetButton, indexButton);
}
@Override
}
public static class ConfigListWidget extends ContainerObjectSelectionList<ButtonEntry>
{
Font textRenderer;
public ConfigListWidget(Minecraft minecraftClient, int i, int j, int k, int l, int m)
{
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
textRenderer = minecraftClient.font;
}
public void addButton(AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text)
{
this.addEntry(ButtonEntry.create(button, text, resetButton, indexButton));
}
@Override
public int getRowWidth()
{
return 10000;
}
public Optional<AbstractWidget> getHoveredButton(double mouseX, double mouseY)
{
for (ButtonEntry buttonEntry : this.children())
{
if (buttonEntry.button != null && buttonEntry.button.isMouseOver(mouseX, mouseY))
{
return Optional.of(buttonEntry.button);
}
}
return Optional.empty();
}
}
public static class ButtonEntry extends ContainerObjectSelectionList.Entry<ButtonEntry>
{
private static final Font textRenderer = Minecraft.getInstance().font;
public final AbstractWidget button;
private final AbstractWidget resetButton;
private final AbstractWidget indexButton;
private final Component text;
private final List<AbstractWidget> children = new ArrayList<>();
public static final Map<AbstractWidget, Component> buttonsWithText = new HashMap<>();
private ButtonEntry(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
{
buttonsWithText.put(button, text);
this.button = button;
this.resetButton = resetButton;
this.text = text;
this.indexButton = indexButton;
if (button != null)
children.add(button);
if (resetButton != null)
children.add(resetButton);
if (indexButton != null)
children.add(indexButton);
}
public static ButtonEntry create(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
{
return new ButtonEntry(button, text, resetButton, indexButton);
}
@Override
#if PRE_MC_1_20_1
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
#else
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
#endif
{
if (button != null) {
SetY(button, y);
button.render(matrices, mouseX, mouseY, tickDelta);
}
if (resetButton != null) {
SetY(resetButton, y);
resetButton.render(matrices, mouseX, mouseY, tickDelta);
}
if (indexButton != null) {
SetY(indexButton, y);
indexButton.render(matrices, mouseX, mouseY, tickDelta);
}
if (text != null && (!text.getString().contains("spacer") || button != null))
{
if (button != null)
{
SetY(button, y);
button.render(matrices, mouseX, mouseY, tickDelta);
}
if (resetButton != null)
{
SetY(resetButton, y);
resetButton.render(matrices, mouseX, mouseY, tickDelta);
}
if (indexButton != null)
{
SetY(indexButton, y);
indexButton.render(matrices, mouseX, mouseY, tickDelta);
}
if (text != null && (!text.getString().contains("spacer") || button != null))
#if PRE_MC_1_20_1
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
#else
matrices.drawString(textRenderer, text, 12, y + 5, 0xFFFFFF);
matrices.drawString(textRenderer, text, 12, y + 5, 0xFFFFFF);
#endif
}
@Override
public List<? extends GuiEventListener> children() {
return children;
}
// Only for 1.17 and over
// Remove in 1.16 and below
}
@Override
public List<? extends GuiEventListener> children()
{
return children;
}
// Only for 1.17 and over
// Remove in 1.16 and below
#if POST_MC_1_17_1
@Override
public List<? extends NarratableEntry> narratables() {
return children;
}
@Override
public List<? extends NarratableEntry> narratables()
{
return children;
}
#endif
}
}
}
@@ -12,53 +12,66 @@ import net.minecraft.network.chat.Component;
import java.util.List;
public class DhScreen extends Screen {
protected DhScreen(Component $$0) {
super($$0);
}
// addRenderableWidget in 1.17 and over
// addButton in 1.16 and below
protected Button addBtn(Button button) {
public class DhScreen extends Screen
{
protected DhScreen(Component $$0)
{
super($$0);
}
// addRenderableWidget in 1.17 and over
// addButton in 1.16 and below
protected Button addBtn(Button button)
{
#if PRE_MC_1_17_1
return this.addButton(button);
#else
return this.addRenderableWidget(button);
return this.addRenderableWidget(button);
#endif
}
#if PRE_MC_1_20_1
protected void DhDrawCenteredString(PoseStack guiStack, Font font, Component text, int x, int y, int color) {
drawCenteredString(guiStack, font, text, x, y, color);
}
protected void DhDrawString(PoseStack guiStack, Font font, Component text, int x, int y, int color) {
drawString(guiStack, font, text, x, y, color);
}
protected void DhRenderTooltip(PoseStack guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y) {
renderTooltip(guiStack, text, x, y);
}
protected void DhRenderComponentTooltip(PoseStack guiStack, Font font, List<Component> comp, int x, int y) {
renderComponentTooltip(guiStack, comp, x, y);
}
protected void DhRenderTooltip(PoseStack guiStack, Font font, Component comp, int x, int y) {
renderTooltip(guiStack, comp, x, y);
}
#else
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color) {
guiStack.drawCenteredString(font, text, x, y, color);
}
protected void DhDrawString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color) {
guiStack.drawString(font, text, x, y, color);
}
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y) {
guiStack.renderTooltip(font, text, x, y);
}
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y) {
guiStack.renderComponentTooltip(font, comp, x, y);
}
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y) {
guiStack.renderTooltip(font, text, x, y);
}
}
#if PRE_MC_1_20_1
protected void DhDrawCenteredString(PoseStack guiStack, Font font, Component text, int x, int y, int color)
{
drawCenteredString(guiStack, font, text, x, y, color);
}
protected void DhDrawString(PoseStack guiStack, Font font, Component text, int x, int y, int color)
{
drawString(guiStack, font, text, x, y, color);
}
protected void DhRenderTooltip(PoseStack guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
{
renderTooltip(guiStack, text, x, y);
}
protected void DhRenderComponentTooltip(PoseStack guiStack, Font font, List<Component> comp, int x, int y)
{
renderComponentTooltip(guiStack, comp, x, y);
}
protected void DhRenderTooltip(PoseStack guiStack, Font font, Component comp, int x, int y)
{
renderTooltip(guiStack, comp, x, y);
}
#else
protected void DhDrawCenteredString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
{
guiStack.drawCenteredString(font, text, x, y, color);
}
protected void DhDrawString(GuiGraphics guiStack, Font font, Component text, int x, int y, int color)
{
guiStack.drawString(font, text, x, y, color);
}
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, List<? extends net.minecraft.util.FormattedCharSequence> text, int x, int y)
{
guiStack.renderTooltip(font, text, x, y);
}
protected void DhRenderComponentTooltip(GuiGraphics guiStack, Font font, List<Component> comp, int x, int y)
{
guiStack.renderComponentTooltip(font, comp, x, y);
}
protected void DhRenderTooltip(GuiGraphics guiStack, Font font, Component text, int x, int y)
{
guiStack.renderTooltip(font, text, x, y);
}
#endif
}
@@ -18,24 +18,26 @@ public class GetConfigScreen
OpenGL, // This was just an attempt, it didn't work out, and we are going to change to javafx soon (as soon as that works)
JavaFX;
}
public static Screen getScreen(Screen parent)
public static Screen getScreen(Screen parent)
{
// Generate the language
// This shouldn't be here, but I need a way to test it after Minecraft inits its assets
//System.out.println(ConfigBase.INSTANCE.generateLang(false, true));
// Generate the language
// This shouldn't be here, but I need a way to test it after Minecraft inits its assets
//System.out.println(ConfigBase.INSTANCE.generateLang(false, true));
switch (useScreen)
switch (useScreen)
{
case Classic:
return ClassicConfigGUI.getScreen(ConfigBase.INSTANCE, parent, "client");
case OpenGL: MinecraftScreen.getScreen(parent, new OpenGLConfigScreen(), ModInfo.ID + ".title");
return ClassicConfigGUI.getScreen(ConfigBase.INSTANCE, parent, "client");
case OpenGL:
MinecraftScreen.getScreen(parent, new OpenGLConfigScreen(), ModInfo.ID + ".title");
return null;
// case JavaFX -> MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new JavaScreenHandlerScreen.ExampleScreen()), ModInfo.ID + ".title");
case JavaFX:
case JavaFX:
return MinecraftScreen.getScreen(parent, new JavaScreenHandlerScreen(new ConfigScreen()), ModInfo.ID + ".title");
default:
return null;
}
}
}
}
}
@@ -10,56 +10,63 @@ import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
#endif
public class GuiHelper {
/**
* Helper static methods for versional compat
*/
public static Button MakeBtn(Component base, int a, int b, int c, int d, Button.OnPress action) {
public class GuiHelper
{
/**
* Helper static methods for versional compat
*/
public static Button MakeBtn(Component base, int a, int b, int c, int d, Button.OnPress action)
{
#if PRE_MC_1_19_4
return new Button(a, b, c, d, base, action);
return new Button(a, b, c, d, base, action);
#else
return Button.builder(base, action).bounds(a,b,c,d).build();
return Button.builder(base, action).bounds(a, b, c, d).build();
#endif
}
public static MutableComponent TextOrLiteral(String text) {
}
public static MutableComponent TextOrLiteral(String text)
{
#if PRE_MC_1_19_2
return new TextComponent(text);
return new TextComponent(text);
#else
return Component.literal(text);
return Component.literal(text);
#endif
}
public static MutableComponent TextOrTranslatable(String text) {
}
public static MutableComponent TextOrTranslatable(String text)
{
#if PRE_MC_1_19_2
return new TextComponent(text);
return new TextComponent(text);
#else
return Component.translatable(text);
return Component.translatable(text);
#endif
}
public static MutableComponent Translatable(String text, Object... args) {
}
public static MutableComponent Translatable(String text, Object... args)
{
#if PRE_MC_1_19_2
return new TranslatableComponent(text, args);
return new TranslatableComponent(text, args);
#else
return Component.translatable(text, args);
return Component.translatable(text, args);
#endif
}
public static void SetX(AbstractWidget w, int x) {
}
public static void SetX(AbstractWidget w, int x)
{
#if PRE_MC_1_19_4
w.x = x;
w.x = x;
#else
w.setX(x);
w.setX(x);
#endif
}
public static void SetY(AbstractWidget w, int y) {
}
public static void SetY(AbstractWidget w, int y)
{
#if PRE_MC_1_19_4
w.y = y;
w.y = y;
#else
w.setY(y);
w.setY(y);
#endif
}
}
}
@@ -3,15 +3,19 @@ package com.seibel.distanthorizons.common.wrappers.gui;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
import net.minecraft.client.resources.language.I18n;
public class LangWrapper implements ILangWrapper {
public static final LangWrapper INSTANCE = new LangWrapper();
@Override
public boolean langExists(String str) {
return I18n.exists(str);
}
@Override
public String getLang(String str) {
return I18n.get(str);
}
public class LangWrapper implements ILangWrapper
{
public static final LangWrapper INSTANCE = new LangWrapper();
@Override
public boolean langExists(String str)
{
return I18n.exists(str);
}
@Override
public String getLang(String str)
{
return I18n.get(str);
}
}
@@ -14,109 +14,125 @@ import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.util.*;
public class MinecraftScreen {
public static Screen getScreen(Screen parent, AbstractScreen screen, String translationName) {
return new ConfigScreenRenderer(parent, screen, translationName);
}
private static class ConfigScreenRenderer extends DhScreen {
private final Screen parent;
private ConfigListWidget list;
private AbstractScreen screen;
#if PRE_MC_1_19_2
public static net.minecraft.network.chat.TranslatableComponent translate (String str, Object... args) {
return new net.minecraft.network.chat.TranslatableComponent(str, args);
}
#else
public static net.minecraft.network.chat.MutableComponent translate (String str, Object... args) {
return net.minecraft.network.chat.Component.translatable(str, args);
}
public class MinecraftScreen
{
public static Screen getScreen(Screen parent, AbstractScreen screen, String translationName)
{
return new ConfigScreenRenderer(parent, screen, translationName);
}
private static class ConfigScreenRenderer extends DhScreen
{
private final Screen parent;
private ConfigListWidget list;
private AbstractScreen screen;
#if PRE_MC_1_19_2
public static net.minecraft.network.chat.TranslatableComponent translate(String str, Object... args)
{
return new net.minecraft.network.chat.TranslatableComponent(str, args);
}
#else
public static net.minecraft.network.chat.MutableComponent translate(String str, Object... args)
{
return net.minecraft.network.chat.Component.translatable(str, args);
}
#endif
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName) {
super(translate(translationName));
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
this.parent = parent;
this.screen = screen;
}
@Override
protected void init() {
super.init(); // Init Minecraft's screen
Window mcWindow = this.minecraft.getWindow();
screen.width = mcWindow.getWidth();
screen.height = mcWindow.getHeight();
screen.scaledWidth = this.width;
screen.scaledHeight = this.height;
screen.init(); // Init our own config screen
this.list = new ConfigListWidget(this.minecraft, this.width, this.height, 0, this.height, 25); // Select the area to tint
if (this.minecraft != null && this.minecraft.level != null) // Check if in game
this.list.setRenderBackground(false); // Disable from rendering
this.addWidget(this.list); // Add the tint to the things to be rendered
}
@Override
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName)
{
super(translate(translationName));
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
this.parent = parent;
this.screen = screen;
}
@Override
protected void init()
{
super.init(); // Init Minecraft's screen
Window mcWindow = this.minecraft.getWindow();
screen.width = mcWindow.getWidth();
screen.height = mcWindow.getHeight();
screen.scaledWidth = this.width;
screen.scaledHeight = this.height;
screen.init(); // Init our own config screen
this.list = new ConfigListWidget(this.minecraft, this.width, this.height, 0, this.height, 25); // Select the area to tint
if (this.minecraft != null && this.minecraft.level != null) // Check if in game
this.list.setRenderBackground(false); // Disable from rendering
this.addWidget(this.list); // Add the tint to the things to be rendered
}
@Override
#if PRE_MC_1_20_1
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
#else
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
#endif
{
this.renderBackground(matrices); // Render background
this.list.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
screen.mouseX = mouseX;
screen.mouseY = mouseY;
screen.render(delta); // Render everything on the main screen
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
}
@Override
public void resize(Minecraft mc, int width, int height) {
super.resize(mc, width, height); // Resize Minecraft's screen
Window mcWindow = this.minecraft.getWindow();
screen.width = mcWindow.getWidth();
screen.height = mcWindow.getHeight();
screen.scaledWidth = this.width;
screen.scaledHeight = this.height;
screen.onResize(); // Resize our screen
}
@Override
public void tick() {
super.tick(); // Tick Minecraft's screen
screen.tick(); // Tick our screen
if (screen.close) // If we decide to close the screen, then actually close the screen
onClose();
}
@Override
public void onClose() {
screen.onClose(); // Close our screen
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
}
@Override
public void onFilesDrop(@NotNull List<Path> files) {
screen.onFilesDrop(files);
}
// For checking if it should close when you press the escape key
@Override
public boolean shouldCloseOnEsc() {
return screen.shouldCloseOnEsc;
}
}
public static class ConfigListWidget extends ContainerObjectSelectionList {
public ConfigListWidget(Minecraft minecraftClient, int i, int j, int k, int l, int m) {
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
}
}
{
this.renderBackground(matrices); // Render background
this.list.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
screen.mouseX = mouseX;
screen.mouseY = mouseY;
screen.render(delta); // Render everything on the main screen
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
}
@Override
public void resize(Minecraft mc, int width, int height)
{
super.resize(mc, width, height); // Resize Minecraft's screen
Window mcWindow = this.minecraft.getWindow();
screen.width = mcWindow.getWidth();
screen.height = mcWindow.getHeight();
screen.scaledWidth = this.width;
screen.scaledHeight = this.height;
screen.onResize(); // Resize our screen
}
@Override
public void tick()
{
super.tick(); // Tick Minecraft's screen
screen.tick(); // Tick our screen
if (screen.close) // If we decide to close the screen, then actually close the screen
onClose();
}
@Override
public void onClose()
{
screen.onClose(); // Close our screen
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
}
@Override
public void onFilesDrop(@NotNull List<Path> files)
{
screen.onFilesDrop(files);
}
// For checking if it should close when you press the escape key
@Override
public boolean shouldCloseOnEsc()
{
return screen.shouldCloseOnEsc;
}
}
public static class ConfigListWidget extends ContainerObjectSelectionList
{
public ConfigListWidget(Minecraft minecraftClient, int i, int j, int k, int l, int m)
{
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.gui;
import com.mojang.blaze3d.systems.RenderSystem;
@@ -36,44 +36,50 @@ import net.minecraft.client.renderer.GameRenderer;
* Creates a button with a texture on it
*/
// TODO: Is this still needed? Can we switch to vanilla's ImageButton?
public class TexturedButtonWidget extends ImageButton {
#if POST_MC_1_17_1
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction) {
super(x, y, width, height, u, v, texture, pressAction);
}
public class TexturedButtonWidget extends ImageButton
{
#if POST_MC_1_17_1
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction)
{
super(x, y, width, height, u, v, texture, pressAction);
}
#endif
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction) {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction);
}
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, Component text) {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text);
}
#if PRE_MC_1_19_2
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, OnTooltip tooltipSupplier, Component text) {
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, tooltipSupplier, text);
}
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction)
{
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction);
}
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, Component text)
{
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text);
}
#if PRE_MC_1_19_2
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, OnTooltip tooltipSupplier, Component text)
{
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, tooltipSupplier, text);
}
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta)
{
#if PRE_MC_1_17_1
Minecraft.getInstance().getTextureManager().bind(WIDGETS_LOCATION);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, this.alpha);
#else
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, WIDGETS_LOCATION);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, WIDGETS_LOCATION);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
#endif
int i = this.getYImage(this.isHovered);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
super.renderButton(matrices, mouseX, mouseY, delta);
}
int i = this.getYImage(this.isHovered);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
super.renderButton(matrices, mouseX, mouseY, delta);
}
#endif
}
@@ -37,162 +37,182 @@ import java.util.*;
*/
// TODO: After finishing the config, rewrite this in openGL as well
// TODO: Make this
public class ChangelogScreen extends DhScreen {
private Screen parent;
private String versionID;
private List<String> changelog;
private TextArea changelogArea;
public ChangelogScreen(Screen parent) {
this(parent, null);
if (!ModrinthGetter.initted) // Make sure the modrinth stuff is initted
ModrinthGetter.init();
if (!ModrinthGetter.initted) // If its not initted the just close the screen
onClose();
setupChangelog(ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()));
}
public ChangelogScreen(Screen parent, String versionID) {
super(Translatable(ModInfo.ID + ".updater.title"));
this.parent = parent;
this.versionID = versionID;
if (versionID != null)
setupChangelog(versionID);
}
private void setupChangelog(String versionID) {
this.changelog = new ArrayList<>();
// Put the new version name at the very top of the change log
this.changelog.add("§lChangelog for " + ModrinthGetter.releaseNames.get(versionID) + "§r");
this.changelog.add("");
this.changelog.add("");
// 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");
// Makes the words wrap around to not go off the screen
for (String str: unwrappedChangelog) {
this.changelog.addAll(
MarkdownFormatter.splitString(str, 75)
);
}
// Debugging
public class ChangelogScreen extends DhScreen
{
private Screen parent;
private String versionID;
private List<String> changelog;
private TextArea changelogArea;
public ChangelogScreen(Screen parent)
{
this(parent, null);
if (!ModrinthGetter.initted) // Make sure the modrinth stuff is initted
ModrinthGetter.init();
if (!ModrinthGetter.initted) // If its not initted the just close the screen
onClose();
setupChangelog(ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion()));
}
public ChangelogScreen(Screen parent, String versionID)
{
super(Translatable(ModInfo.ID + ".updater.title"));
this.parent = parent;
this.versionID = versionID;
if (versionID != null)
setupChangelog(versionID);
}
private void setupChangelog(String versionID)
{
this.changelog = new ArrayList<>();
// Put the new version name at the very top of the change log
this.changelog.add("§lChangelog for " + ModrinthGetter.releaseNames.get(versionID) + "§r");
this.changelog.add("");
this.changelog.add("");
// 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");
// Makes the words wrap around to not go off the screen
for (String str : unwrappedChangelog)
{
this.changelog.addAll(
MarkdownFormatter.splitString(str, 75)
);
}
// Debugging
// System.out.println(this.changelog);
}
@Override
protected void init() {
super.init();
this.addBtn( // Close
MakeBtn(Translatable(ModInfo.ID + ".general.back"), 5, this.height - 25, 100, 20, (btn) -> {
this.onClose();
})
);
this.changelogArea = new TextArea(this.minecraft, this.width*2, this.height, 32, this.height - 32, 10);
for (int i = 0; i < changelog.size(); i++) {
this.changelogArea.addButton( TextOrLiteral(changelog.get(i)));
}
@Override
protected void init()
{
super.init();
this.addBtn( // Close
MakeBtn(Translatable(ModInfo.ID + ".general.back"), 5, this.height - 25, 100, 20, (btn) -> {
this.onClose();
})
);
this.changelogArea = new TextArea(this.minecraft, this.width * 2, this.height, 32, this.height - 32, 10);
for (int i = 0; i < changelog.size(); i++)
{
this.changelogArea.addButton(TextOrLiteral(changelog.get(i)));
// drawString(matrices, this.font, changelog.get(i), this.width / 2 - 175, this.height / 2 - 100 + i*10, 0xFFFFFF);
}
}
@Override
}
}
@Override
#if PRE_MC_1_20_1
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
#else
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
#endif
{
this.renderBackground(matrices); // Render background
// Set the scroll position to the mouse height relative to the screen
// This is a bit of a hack as we cannot scroll on this area
double scrollAmount = ((double) mouseY)/((double) this.height) * 1.1 * this.changelogArea.getMaxScroll();
{
this.renderBackground(matrices); // Render background
// Set the scroll position to the mouse height relative to the screen
// This is a bit of a hack as we cannot scroll on this area
double scrollAmount = ((double) mouseY) / ((double) this.height) * 1.1 * this.changelogArea.getMaxScroll();
#if MC_1_16_5 || MC_1_17_1
this.changelogArea.setScrollAmount(scrollAmount);
this.changelogArea.setScrollAmount(scrollAmount);
#else
this.changelogArea.scrollAmount = scrollAmount;
#endif
this.changelogArea.render(matrices, mouseX, mouseY, delta); // Render the changelog
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
}
@Override
public void onClose() {
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
}
public static class TextArea extends ContainerObjectSelectionList<ButtonEntry> {
Font textRenderer;
public TextArea(Minecraft minecraftClient, int i, int j, int k, int l, int m) {
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
textRenderer = minecraftClient.font;
}
public void addButton(Component text) {
this.addEntry(ButtonEntry.create(text));
}
@Override
public int getRowWidth() {
return 10000;
}
}
public static class ButtonEntry extends ContainerObjectSelectionList.Entry<ButtonEntry>
{
private static final Font textRenderer = Minecraft.getInstance().font;
private final Component text;
private final List<AbstractWidget> children = new ArrayList<>();
private ButtonEntry(Component text) {
this.text = text;
}
public static ButtonEntry create(Component text) {
return new ButtonEntry(text);
}
#if PRE_MC_1_20_1
@Override
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
}
#else
@Override
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
matrices.drawString(textRenderer, text, 12, y + 5, 0xFFFFFF);
}
this.changelogArea.render(matrices, mouseX, mouseY, delta); // Render the changelog
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
DhDrawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
}
@Override
public void onClose()
{
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
}
public static class TextArea extends ContainerObjectSelectionList<ButtonEntry>
{
Font textRenderer;
public TextArea(Minecraft minecraftClient, int i, int j, int k, int l, int m)
{
super(minecraftClient, i, j, k, l, m);
this.centerListVertically = false;
textRenderer = minecraftClient.font;
}
public void addButton(Component text)
{
this.addEntry(ButtonEntry.create(text));
}
@Override
public int getRowWidth()
{
return 10000;
}
}
public static class ButtonEntry extends ContainerObjectSelectionList.Entry<ButtonEntry>
{
private static final Font textRenderer = Minecraft.getInstance().font;
private final Component text;
private final List<AbstractWidget> children = new ArrayList<>();
private ButtonEntry(Component text)
{
this.text = text;
}
public static ButtonEntry create(Component text)
{
return new ButtonEntry(text);
}
#if PRE_MC_1_20_1
@Override
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
{
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
}
#else
@Override
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
{
matrices.drawString(textRenderer, text, 12, y + 5, 0xFFFFFF);
}
#endif
@Override
public List<? extends GuiEventListener> children() {
return children;
}
@Override
public List<? extends GuiEventListener> children()
{
return children;
}
#if POST_MC_1_17_1
@Override
public List<? extends NarratableEntry> narratables() {
return children;
}
@Override
public List<? extends NarratableEntry> narratables()
{
return children;
}
#endif
}
}
}
@@ -29,116 +29,126 @@ import java.util.*;
*/
// TODO: After finishing the config, rewrite this in openGL as well
// and also maybe add this suggestion https://discord.com/channels/881614130614767666/1035863487110467625/1035949054485594192
public class UpdateModScreen extends DhScreen {
private Screen parent;
private String newVersionID;
public UpdateModScreen(Screen parent, String newVersionID) {
super(Translatable(ModInfo.ID + ".updater.title"));
this.parent = parent;
this.newVersionID = newVersionID;
}
@Override
protected void init() {
super.init();
try {
// We cannot get assets from the root of the mod so we use this hack
// TODO: Load the icon.png and logo.png in the mod initialise rather than here
ResourceLocation logoLocation = new ResourceLocation(ModInfo.ID, "logo.png");
Minecraft.getInstance().getTextureManager().register(
logoLocation,
new DynamicTexture(NativeImage.read(JarUtils.accessFile("logo.png")))
);
// Logo image
this.addBtn(new ImageButton(
// Where the button is on the screen
this.width / 2 - 65, this.height / 2 - 110,
// Width and height of the button
130, 65,
// Offset
0, 0,
// Some textuary stuff
0, logoLocation, 130, 65,
// Create the button and tell it where to go
// For now it goes to the client option by default
(buttonWidget) -> System.out.println("Nice, you found an easter egg :)"), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
// Add a title to the button
Translatable(ModInfo.ID + ".updater.title")
));
} catch (Exception e) { e.printStackTrace(); }
this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 97, this.height / 2 + 8,
// Width and height of the button
20, 20,
// Offset
0, 0,
// Some textuary stuff
0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20,
// Create the button and tell it where to go
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
// Add a title to the button
Translatable(ModInfo.ID + ".updater.title")
));
this.addBtn( // Update
MakeBtn(Translatable(ModInfo.ID + ".updater.update"), this.width / 2 - 75, this.height / 2 + 8, 150, 20, (btn) -> {
SelfUpdater.updateMod();
this.onClose();
})
);
this.addBtn( // Silent update
MakeBtn(Translatable(ModInfo.ID + ".updater.silent"), this.width / 2 - 75, this.height / 2 + 30, 150, 20, (btn) -> {
Config.Client.Advanced.AutoUpdater.enableSilentUpdates.set(true);
SelfUpdater.updateMod();
this.onClose();
})
);
this.addBtn( // Later (not now)
MakeBtn(Translatable(ModInfo.ID + ".updater.later"), this.width / 2 + 2, this.height / 2 + 70, 100, 20, (btn) -> {
this.onClose();
})
);
this.addBtn( // Never
MakeBtn(Translatable(ModInfo.ID + ".updater.never"), this.width / 2 - 102, this.height / 2 + 70, 100, 20, (btn) -> {
Config.Client.Advanced.AutoUpdater.enableAutoUpdater.set(false);
this.onClose();
})
);
}
@Override
public class UpdateModScreen extends DhScreen
{
private Screen parent;
private String newVersionID;
public UpdateModScreen(Screen parent, String newVersionID)
{
super(Translatable(ModInfo.ID + ".updater.title"));
this.parent = parent;
this.newVersionID = newVersionID;
}
@Override
protected void init()
{
super.init();
try
{
// We cannot get assets from the root of the mod so we use this hack
// TODO: Load the icon.png and logo.png in the mod initialise rather than here
ResourceLocation logoLocation = new ResourceLocation(ModInfo.ID, "logo.png");
Minecraft.getInstance().getTextureManager().register(
logoLocation,
new DynamicTexture(NativeImage.read(JarUtils.accessFile("logo.png")))
);
// Logo image
this.addBtn(new ImageButton(
// Where the button is on the screen
this.width / 2 - 65, this.height / 2 - 110,
// Width and height of the button
130, 65,
// Offset
0, 0,
// Some textuary stuff
0, logoLocation, 130, 65,
// Create the button and tell it where to go
// For now it goes to the client option by default
(buttonWidget) -> System.out.println("Nice, you found an easter egg :)"), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
// Add a title to the button
Translatable(ModInfo.ID + ".updater.title")
));
}
catch (Exception e)
{
e.printStackTrace();
}
this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 97, this.height / 2 + 8,
// Width and height of the button
20, 20,
// Offset
0, 0,
// Some textuary stuff
0, new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"), 20, 20,
// Create the button and tell it where to go
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(new ChangelogScreen(this, this.newVersionID)), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
// Add a title to the button
Translatable(ModInfo.ID + ".updater.title")
));
this.addBtn( // Update
MakeBtn(Translatable(ModInfo.ID + ".updater.update"), this.width / 2 - 75, this.height / 2 + 8, 150, 20, (btn) -> {
SelfUpdater.updateMod();
this.onClose();
})
);
this.addBtn( // Silent update
MakeBtn(Translatable(ModInfo.ID + ".updater.silent"), this.width / 2 - 75, this.height / 2 + 30, 150, 20, (btn) -> {
Config.Client.Advanced.AutoUpdater.enableSilentUpdates.set(true);
SelfUpdater.updateMod();
this.onClose();
})
);
this.addBtn( // Later (not now)
MakeBtn(Translatable(ModInfo.ID + ".updater.later"), this.width / 2 + 2, this.height / 2 + 70, 100, 20, (btn) -> {
this.onClose();
})
);
this.addBtn( // Never
MakeBtn(Translatable(ModInfo.ID + ".updater.never"), this.width / 2 - 102, this.height / 2 + 70, 100, 20, (btn) -> {
Config.Client.Advanced.AutoUpdater.enableAutoUpdater.set(false);
this.onClose();
})
);
}
@Override
#if PRE_MC_1_20_1
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
#else
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
#endif
{
this.renderBackground(matrices); // Render background
// Render the text's
DhDrawCenteredString(matrices, this.font, Translatable(ModInfo.ID + ".updater.text1"), this.width / 2, this.height / 2 - 35, 0xFFFFFF);
DhDrawCenteredString(matrices, this.font, Translatable(ModInfo.ID + ".updater.text2", ModInfo.VERSION, ModrinthGetter.releaseNames.get(this.newVersionID)), this.width / 2, this.height / 2 -20, 0x52FD52);
// TODO: add the tooltips for the buttons
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
// TODO: Add tooltips
}
@Override
public void onClose() {
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
}
{
this.renderBackground(matrices); // Render background
// Render the text's
DhDrawCenteredString(matrices, this.font, Translatable(ModInfo.ID + ".updater.text1"), this.width / 2, this.height / 2 - 35, 0xFFFFFF);
DhDrawCenteredString(matrices, this.font, Translatable(ModInfo.ID + ".updater.text2", ModInfo.VERSION, ModrinthGetter.releaseNames.get(this.newVersionID)), this.width / 2, this.height / 2 - 20, 0x52FD52);
// TODO: add the tooltips for the buttons
super.render(matrices, mouseX, mouseY, delta); // Render the buttons
// TODO: Add tooltips
}
@Override
public void onClose()
{
Objects.requireNonNull(minecraft).setScreen(this.parent); // Goto the parent screen
}
}
@@ -63,243 +63,246 @@ import org.jetbrains.annotations.Nullable;
//@Environment(EnvType.CLIENT)
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
public final Minecraft mc = Minecraft.getInstance();
/**
* The lightmap for the current:
* Time, dimension, brightness setting, etc.
*/
private NativeImage lightMap = null;
private ProfilerWrapper profilerWrapper;
private MinecraftClientWrapper()
{
}
//================//
// helper methods //
//================//
/**
* This should be called at the beginning of every frame to
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
* <p>
* LightMaps and other time sensitive objects fall in this category. <br> <br>
* <p>
* This doesn't affect OpenGL objects in any way.
*/
@Override
public void clearFrameObjectCache()
{
lightMap = null;
}
//=================//
// method wrappers //
//=================//
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
@Override
public float getShade(EDhDirection lodDirection)
{
ELodShading lodShading = Config.Client.Advanced.Graphics.AdvancedGraphics.lodShading.get();
switch (lodShading)
{
default:
case MINECRAFT:
if (this.mc.level != null)
{
Direction mcDir = McObjectConverter.Convert(lodDirection);
return this.mc.level.getShade(mcDir, true);
}
else
{
return 0.0f;
}
case OLD_LIGHTING:
switch (lodDirection)
{
case DOWN:
return 0.5F;
default:
case UP:
return 1.0F;
case NORTH:
case SOUTH:
return 0.8F;
case WEST:
case EAST:
return 0.6F;
}
case NONE:
return 1.0F;
}
}
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
@Override
public boolean hasSinglePlayerServer() { return mc.hasSingleplayerServer(); }
@Override
public boolean clientConnectedToDedicatedServer() { return mc.getCurrentServer() != null && !this.hasSinglePlayerServer(); }
@Override
public String getCurrentServerName() { return mc.getCurrentServer().name; }
@Override
public String getCurrentServerIp() { return mc.getCurrentServer().ip; }
@Override
public String getCurrentServerVersion()
{
return mc.getCurrentServer().version.getString();
}
//=============//
// Simple gets //
//=============//
public LocalPlayer getPlayer()
{
return mc.player;
}
@Override
public boolean playerExists()
{
return mc.player != null;
}
@Override
public UUID getPlayerUUID() {
return getPlayer().getUUID();
}
@Override
public DhBlockPos getPlayerBlockPos()
{
BlockPos playerPos = getPlayer().blockPosition();
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
}
@Override
public DhChunkPos getPlayerChunkPos()
{
public final Minecraft mc = Minecraft.getInstance();
/**
* The lightmap for the current:
* Time, dimension, brightness setting, etc.
*/
private NativeImage lightMap = null;
private ProfilerWrapper profilerWrapper;
private MinecraftClientWrapper()
{
}
//================//
// helper methods //
//================//
/**
* This should be called at the beginning of every frame to
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
* <p>
* LightMaps and other time sensitive objects fall in this category. <br> <br>
* <p>
* This doesn't affect OpenGL objects in any way.
*/
@Override
public void clearFrameObjectCache()
{
lightMap = null;
}
//=================//
// method wrappers //
//=================//
@Override
public float getShade(EDhDirection lodDirection)
{
ELodShading lodShading = Config.Client.Advanced.Graphics.AdvancedGraphics.lodShading.get();
switch (lodShading)
{
default:
case MINECRAFT:
if (this.mc.level != null)
{
Direction mcDir = McObjectConverter.Convert(lodDirection);
return this.mc.level.getShade(mcDir, true);
}
else
{
return 0.0f;
}
case OLD_LIGHTING:
switch (lodDirection)
{
case DOWN:
return 0.5F;
default:
case UP:
return 1.0F;
case NORTH:
case SOUTH:
return 0.8F;
case WEST:
case EAST:
return 0.6F;
}
case NONE:
return 1.0F;
}
}
@Override
public boolean hasSinglePlayerServer() { return mc.hasSingleplayerServer(); }
@Override
public boolean clientConnectedToDedicatedServer() { return mc.getCurrentServer() != null && !this.hasSinglePlayerServer(); }
@Override
public String getCurrentServerName() { return mc.getCurrentServer().name; }
@Override
public String getCurrentServerIp() { return mc.getCurrentServer().ip; }
@Override
public String getCurrentServerVersion()
{
return mc.getCurrentServer().version.getString();
}
//=============//
// Simple gets //
//=============//
public LocalPlayer getPlayer()
{
return mc.player;
}
@Override
public boolean playerExists()
{
return mc.player != null;
}
@Override
public UUID getPlayerUUID()
{
return getPlayer().getUUID();
}
@Override
public DhBlockPos getPlayerBlockPos()
{
BlockPos playerPos = getPlayer().blockPosition();
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
}
@Override
public DhChunkPos getPlayerChunkPos()
{
#if PRE_MC_1_17_1
ChunkPos playerPos = new ChunkPos(getPlayer().blockPosition());
#else
ChunkPos playerPos = getPlayer().chunkPosition();
ChunkPos playerPos = getPlayer().chunkPosition();
#endif
return new DhChunkPos(playerPos.x, playerPos.z);
}
public ModelManager getModelManager()
{
return mc.getModelManager();
}
@Nullable
@Override
public ILevelWrapper getWrappedClientWorld()
{
return new DhChunkPos(playerPos.x, playerPos.z);
}
public ModelManager getModelManager()
{
return mc.getModelManager();
}
@Nullable
@Override
public ILevelWrapper getWrappedClientWorld()
{
if (mc.level == null)
{
return null;
}
return ClientLevelWrapper.getWrapperIgnoringOverride(this.mc.level);
}
/** Please move over to getInstallationDirectory() */
@Deprecated
@Override
public File getGameDirectory()
{
return getInstallationDirectory();
}
@Override
public IProfilerWrapper getProfiler()
{
if (profilerWrapper == null)
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
else if (mc.getProfiler() != profilerWrapper.profiler)
profilerWrapper.profiler = mc.getProfiler();
return profilerWrapper;
}
/** Returns all worlds available to the server */
@Override
public ArrayList<ILevelWrapper> getAllServerWorlds()
{
ArrayList<ILevelWrapper> worlds = new ArrayList<ILevelWrapper>();
Iterable<ServerLevel> serverWorlds = mc.getSingleplayerServer().getAllLevels();
for (ServerLevel world : serverWorlds)
{
worlds.add(ServerLevelWrapper.getWrapper(world));
}
return worlds;
}
@Override
public void sendChatMessage(String string)
{
LocalPlayer p = getPlayer();
if (p == null) return;
return ClientLevelWrapper.getWrapperIgnoringOverride(this.mc.level);
}
/** Please move over to getInstallationDirectory() */
@Deprecated
@Override
public File getGameDirectory()
{
return getInstallationDirectory();
}
@Override
public IProfilerWrapper getProfiler()
{
if (profilerWrapper == null)
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
else if (mc.getProfiler() != profilerWrapper.profiler)
profilerWrapper.profiler = mc.getProfiler();
return profilerWrapper;
}
/** Returns all worlds available to the server */
@Override
public ArrayList<ILevelWrapper> getAllServerWorlds()
{
ArrayList<ILevelWrapper> worlds = new ArrayList<ILevelWrapper>();
Iterable<ServerLevel> serverWorlds = mc.getSingleplayerServer().getAllLevels();
for (ServerLevel world : serverWorlds)
{
worlds.add(ServerLevelWrapper.getWrapper(world));
}
return worlds;
}
@Override
public void sendChatMessage(String string)
{
LocalPlayer p = getPlayer();
if (p == null) return;
#if PRE_MC_1_19_2
p.sendMessage(new TextComponent(string), getPlayer().getUUID());
p.sendMessage(new TextComponent(string), getPlayer().getUUID());
#else
p.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string));
p.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string));
#endif
}
/**
* Crashes Minecraft, displaying the given errorMessage <br> <br>
* In the following format: <br>
*
* The game crashed whilst <strong>errorMessage</strong> <br>
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
* Exit Code: -1 <br>
*/
@Override
public void crashMinecraft(String errorMessage, Throwable exception)
{
LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...", exception);
CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report);
}
@Override
public Object getOptionsObject()
{
return mc.options;
}
@Override
public boolean isDedicatedServer() {
return false;
}
@Override
public File getInstallationDirectory() {
return mc.gameDirectory;
}
@Override
public void executeOnRenderThread(Runnable runnable) { this.mc.execute(runnable); }
}
/**
* Crashes Minecraft, displaying the given errorMessage <br> <br>
* In the following format: <br>
*
* The game crashed whilst <strong>errorMessage</strong> <br>
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
* Exit Code: -1 <br>
*/
@Override
public void crashMinecraft(String errorMessage, Throwable exception)
{
LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...", exception);
CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report);
}
@Override
public Object getOptionsObject()
{
return mc.options;
}
@Override
public boolean isDedicatedServer()
{
return false;
}
@Override
public File getInstallationDirectory()
{
return mc.gameDirectory;
}
@Override
public void executeOnRenderThread(Runnable runnable) { this.mc.execute(runnable); }
}
@@ -6,18 +6,22 @@ import net.minecraft.server.dedicated.DedicatedServer;
import java.io.File;
//@Environment(EnvType.SERVER)
public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper {
public static final MinecraftDedicatedServerWrapper INSTANCE = new MinecraftDedicatedServerWrapper();
private MinecraftDedicatedServerWrapper() {}
public DedicatedServer dedicatedServer = null;
@Override
public boolean isDedicatedServer() {
return true;
}
@Override
public File getInstallationDirectory() {
if (dedicatedServer == null)
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!");
return dedicatedServer.getServerDirectory();
}
public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper
{
public static final MinecraftDedicatedServerWrapper INSTANCE = new MinecraftDedicatedServerWrapper();
private MinecraftDedicatedServerWrapper() { }
public DedicatedServer dedicatedServer = null;
@Override
public boolean isDedicatedServer()
{
return true;
}
@Override
public File getInstallationDirectory()
{
if (dedicatedServer == null)
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!");
return dedicatedServer.getServerDirectory();
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.minecraft;
import java.awt.Color;
@@ -87,11 +87,11 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
private static final Minecraft MC = Minecraft.getInstance();
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
public LightMapWrapper lightmap = null;
@Override
@@ -146,7 +146,8 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
}
@Override
public Color getFogColor(float partialTicks) {
public Color getFogColor(float partialTicks)
{
#if PRE_MC_1_17_1
float[] colorValues = new float[4];
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
@@ -164,15 +165,18 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
// getSpecialFogColor() is the same as getFogColor()
@Override
public Color getSkyColor() {
if (MC.level.dimensionType().hasSkyLight()) {
public Color getSkyColor()
{
if (MC.level.dimensionType().hasSkyLight())
{
#if PRE_MC_1_17_1
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), MC.getFrameTime());
#else
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime());
#endif
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
} else
}
else
return new Color(0, 0, 0);
}
@@ -229,58 +233,68 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
return height;
}
private RenderTarget getRenderTarget() {
RenderTarget r = null; //MC.levelRenderer.getCloudsTarget();
return r!=null ? r : MC.getMainRenderTarget();
}
@Override
public int getTargetFrameBuffer() {
return getRenderTarget().frameBufferId;
}
private RenderTarget getRenderTarget()
{
RenderTarget r = null; //MC.levelRenderer.getCloudsTarget();
return r != null ? r : MC.getMainRenderTarget();
}
@Override
public int getDepthTextureId() {
public int getTargetFrameBuffer()
{
return getRenderTarget().frameBufferId;
}
@Override
public int getDepthTextureId()
{
return getRenderTarget().getDepthTextureId();
}
@Override
public int getTargetFrameBufferViewportWidth() {
return getRenderTarget().viewWidth;
}
@Override
public int getTargetFrameBufferViewportHeight() {
return getRenderTarget().viewHeight;
}
public int getTargetFrameBufferViewportWidth()
{
return getRenderTarget().viewWidth;
}
@Override
public int getTargetFrameBufferViewportHeight()
{
return getRenderTarget().viewHeight;
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
*/
public boolean usingBackupGetVanillaRenderedChunks = false;
public boolean usingBackupGetVanillaRenderedChunks = false;
@Override
public HashSet<DhChunkPos> getVanillaRenderedChunks() {
public HashSet<DhChunkPos> getVanillaRenderedChunks()
{
ISodiumAccessor sodium = ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
if (sodium != null) {
if (sodium != null)
{
return sodium.getNormalRenderedChunks();
}
IOptifineAccessor optifine = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
if (optifine != null) {
if (optifine != null)
{
HashSet<DhChunkPos> pos = optifine.getNormalRenderedChunks();
if (pos == null)
pos = getMaximumRenderedChunks();
return pos;
}
if (!usingBackupGetVanillaRenderedChunks) {
try {
if (!usingBackupGetVanillaRenderedChunks)
{
try
{
LevelRenderer levelRenderer = MC.levelRenderer;
Collection<LevelRenderer.RenderChunkInfo> chunks =
#if PRE_MC_1_18_2 levelRenderer.renderChunks;
#else levelRenderer.renderChunkStorage.get().renderChunks; #endif
return (chunks.stream().map((chunk) -> {
AABB chunkBoundingBox =
#if PRE_MC_1_18_2 chunk.chunk.bb;
@@ -288,14 +302,19 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
return new DhChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
}).collect(Collectors.toCollection(HashSet::new)));
} catch (LinkageError e) {
try {
}
catch (LinkageError e)
{
try
{
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
+ " Using Backup Method.");
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7eOverdraw prevention will be worse than normal.");
} catch (Exception e2) {
}
catch (Exception e2)
{
}
LOGGER.error("getVanillaRenderedChunks Error: ", e);
usingBackupGetVanillaRenderedChunks = true;
@@ -303,14 +322,16 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
}
return getMaximumRenderedChunks();
}
@Override
public ILightMapWrapper getLightmapWrapper() {
public ILightMapWrapper getLightmapWrapper()
{
return lightmap;
}
@Override
public boolean isFogStateSpecial() {
public boolean isFogStateSpecial()
{
#if PRE_MC_1_17_1
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
FluidState fluidState = camera.getFluidInCamera();
@@ -321,15 +342,18 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
return isUnderWater;
#else
Entity entity = MC.gameRenderer.getMainCamera().getEntity();
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
return MC.gameRenderer.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
#endif
}
public void updateLightmap(NativeImage lightPixels) {
if (lightmap== null) {
public void updateLightmap(NativeImage lightPixels)
{
if (lightmap == null)
{
lightmap = new LightMapWrapper();
}
lightmap.uploadLightmap(lightPixels);
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.minecraft;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
@@ -29,32 +29,33 @@ import net.minecraft.util.profiling.ProfilerFiller;
*/
public class ProfilerWrapper implements IProfilerWrapper
{
public ProfilerFiller profiler;
public ProfilerWrapper(ProfilerFiller newProfiler)
{
profiler = newProfiler;
}
/** starts a new section inside the currently running section */
@Override
public void push(String newSection)
{
profiler.push(newSection);
}
/** ends the currently running section and starts a new one */
@Override
public void popPush(String newSection)
{
profiler.popPush(newSection);
}
/** ends the currently running section */
@Override
public void pop()
{
profiler.pop();
}
public ProfilerFiller profiler;
public ProfilerWrapper(ProfilerFiller newProfiler)
{
profiler = newProfiler;
}
/** starts a new section inside the currently running section */
@Override
public void push(String newSection)
{
profiler.push(newSection);
}
/** ends the currently running section and starts a new one */
@Override
public void popPush(String newSection)
{
profiler.popPush(newSection);
}
/** ends the currently running section */
@Override
public void pop()
{
profiler.pop();
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.misc;
import com.mojang.blaze3d.platform.NativeImage;
@@ -31,39 +31,43 @@ import java.nio.ByteBuffer;
*/
public class LightMapWrapper implements ILightMapWrapper
{
private int textureId = 0;
public LightMapWrapper()
{
}
private void createLightmap(NativeImage image)
{
textureId = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, 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);
}
public void uploadLightmap(NativeImage image)
{
int currentBind = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, textureId);
if (textureId == 0) {
createLightmap(image);
}
// NativeImage::upload(int levelOfDetail, int xOffset, int yOffset, bool shouldCleanup?)
image.upload(0, 0, 0, false);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, currentBind);
}
@Override
public void bind() {
GL32.glBindTexture(GL32.GL_TEXTURE_2D, textureId);
}
@Override
public void unbind() {
GL32.glBindTexture(GL32.GL_TEXTURE_2D, 0);
}
private int textureId = 0;
public LightMapWrapper()
{
}
private void createLightmap(NativeImage image)
{
textureId = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, 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);
}
public void uploadLightmap(NativeImage image)
{
int currentBind = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, textureId);
if (textureId == 0)
{
createLightmap(image);
}
// NativeImage::upload(int levelOfDetail, int xOffset, int yOffset, bool shouldCleanup?)
image.upload(0, 0, 0, false);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, currentBind);
}
@Override
public void bind()
{
GL32.glBindTexture(GL32.GL_TEXTURE_2D, textureId);
}
@Override
public void unbind()
{
GL32.glBindTexture(GL32.GL_TEXTURE_2D, 0);
}
}
@@ -9,40 +9,46 @@ import net.minecraft.server.level.ServerPlayer;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
public class ServerPlayerWrapper implements IServerPlayerWrapper {
private static final ConcurrentMap<ServerPlayer, ServerPlayerWrapper>
serverPlayerWrapperMap = new MapMaker().weakKeys().makeMap();
private final ServerPlayer serverPlayer;
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer)
{
return serverPlayerWrapperMap.computeIfAbsent(serverPlayer, ServerPlayerWrapper::new);
}
private ServerPlayerWrapper(ServerPlayer serverPlayer) {
this.serverPlayer = serverPlayer;
}
public UUID getUUID() {
return serverPlayer.getUUID();
}
public IServerLevelWrapper getLevel()
public class ServerPlayerWrapper implements IServerPlayerWrapper
{
private static final ConcurrentMap<ServerPlayer, ServerPlayerWrapper>
serverPlayerWrapperMap = new MapMaker().weakKeys().makeMap();
private final ServerPlayer serverPlayer;
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer)
{
return serverPlayerWrapperMap.computeIfAbsent(serverPlayer, ServerPlayerWrapper::new);
}
private ServerPlayerWrapper(ServerPlayer serverPlayer)
{
this.serverPlayer = serverPlayer;
}
public UUID getUUID()
{
return serverPlayer.getUUID();
}
public IServerLevelWrapper getLevel()
{
#if PRE_MC_1_20_1
return ServerLevelWrapper.getWrapper(this.serverPlayer.getLevel());
#else
return ServerLevelWrapper.getWrapper(this.serverPlayer.serverLevel());
#endif
}
public Object getWrappedMcObject() {
return serverPlayer;
}
@Override
public String toString() {
return "Wrapped{" + serverPlayer.toString() + "}";
}
}
public Object getWrappedMcObject()
{
return serverPlayer;
}
@Override
public String toString()
{
return "Wrapped{" + serverPlayer.toString() + "}";
}
}
@@ -33,7 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class ClientLevelWrapper implements IClientLevelWrapper
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<ClientLevel, ClientLevelWrapper> LEVEL_WRAPPER_BY_CLIENT_LEVEL = new ConcurrentHashMap<>();
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
private final ClientLevel level;
@@ -45,7 +45,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
// constructor //
//=============//
protected ClientLevelWrapper(ClientLevel level) { this.level = level; }
protected ClientLevelWrapper(ClientLevel level) { this.level = level; }
@@ -72,7 +72,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
@Nullable
@Override
@Override
public IServerLevelWrapper tryGetServerSideWrapper()
{
try
@@ -89,14 +89,14 @@ public class ClientLevelWrapper implements IClientLevelWrapper
// 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
ServerLevelWrapper foundLevelWrapper = null;
// TODO: Surely there is a more efficient way to write this code
// TODO: Surely there is a more efficient way to write this code
for (ServerLevel serverLevel : serverLevels)
{
if (serverLevel.dimension() == this.level.dimension())
{
foundLevelWrapper = ServerLevelWrapper.getWrapper(serverLevel);
break;
break;
}
}
@@ -104,16 +104,18 @@ public class ClientLevelWrapper implements IClientLevelWrapper
}
catch (Exception e)
{
LOGGER.error("Failed to get server side wrapper for client level: "+level);
LOGGER.error("Failed to get server side wrapper for client level: " + level);
return null;
}
}
public static void cleanCheck() {
if (!LEVEL_WRAPPER_BY_CLIENT_LEVEL.isEmpty()) {
LOGGER.warn("{} client levels havn't been freed!", LEVEL_WRAPPER_BY_CLIENT_LEVEL.size());
LEVEL_WRAPPER_BY_CLIENT_LEVEL.clear();
}
}
public static void cleanCheck()
{
if (!LEVEL_WRAPPER_BY_CLIENT_LEVEL.isEmpty())
{
LOGGER.warn("{} client levels havn't been freed!", LEVEL_WRAPPER_BY_CLIENT_LEVEL.size());
LEVEL_WRAPPER_BY_CLIENT_LEVEL.clear();
}
}
@@ -121,83 +123,83 @@ public class ClientLevelWrapper implements IClientLevelWrapper
// base level methods //
//====================//
@Override
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockState)
{
return this.blockMap.getColor(((BlockStateWrapper)blockState).blockState, (BiomeWrapper)biome, pos);
}
@Override
public IDhApiDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
@Override
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper blockState)
{
return this.blockMap.getColor(((BlockStateWrapper) blockState).blockState, (BiomeWrapper) biome, pos);
}
@Override
@Override
public IDhApiDimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
@Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; }
@Override
public int getBlockLight(int x, int y, int z) { return this.level.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z)); }
@Override
public int getSkyLight(int x, int y, int z) { return this.level.getBrightness(LightLayer.SKY, new BlockPos(x,y,z)); }
public ClientLevel getLevel() { return this.level; }
@Override
public boolean hasCeiling() { return this.level.dimensionType().hasCeiling(); }
@Override
public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); }
@Override
public int getHeight() { return this.level.getHeight(); }
@Override
public int getMinHeight()
{
public int getBlockLight(int x, int y, int z) { return this.level.getBrightness(LightLayer.BLOCK, new BlockPos(x, y, z)); }
@Override
public int getSkyLight(int x, int y, int z) { return this.level.getBrightness(LightLayer.SKY, new BlockPos(x, y, z)); }
public ClientLevel getLevel() { return this.level; }
@Override
public boolean hasCeiling() { return this.level.dimensionType().hasCeiling(); }
@Override
public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); }
@Override
public int getHeight() { return this.level.getHeight(); }
@Override
public int getMinHeight()
{
#if PRE_MC_1_17_1
return 0;
#else
return this.level.getMinBuildHeight();
return this.level.getMinBuildHeight();
#endif
}
@Override
public IChunkWrapper tryGetChunk(DhChunkPos pos)
{
if (!this.level.hasChunk(pos.x, pos.z))
{
}
@Override
public IChunkWrapper tryGetChunk(DhChunkPos pos)
{
if (!this.level.hasChunk(pos.x, pos.z))
{
return null;
}
}
ChunkAccess chunk = this.level.getChunk(pos.x, pos.z, ChunkStatus.EMPTY, false);
if (chunk == null)
{
ChunkAccess chunk = this.level.getChunk(pos.x, pos.z, ChunkStatus.EMPTY, false);
if (chunk == null)
{
return null;
}
}
return new ChunkWrapper(chunk, this.level, this);
}
@Override
public boolean hasChunkLoaded(int chunkX, int chunkZ)
{
ChunkSource source = this.level.getChunkSource();
return source.hasChunk(chunkX, chunkZ);
}
@Override
public IBlockStateWrapper getBlockState(DhBlockPos pos)
{
return new ChunkWrapper(chunk, this.level, this);
}
@Override
public boolean hasChunkLoaded(int chunkX, int chunkZ)
{
ChunkSource source = this.level.getChunkSource();
return source.hasChunk(chunkX, chunkZ);
}
@Override
public IBlockStateWrapper getBlockState(DhBlockPos pos)
{
return BlockStateWrapper.fromBlockState(this.level.getBlockState(McObjectConverter.Convert(pos)));
}
@Override
public IBiomeWrapper getBiome(DhBlockPos pos) { return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos))); }
@Override
public ClientLevel getWrappedMcObject() { return this.level; }
@Override
public String toString()
@Override
public IBiomeWrapper getBiome(DhBlockPos pos) { return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos))); }
@Override
public ClientLevel getWrappedMcObject() { return this.level; }
@Override
public String toString()
{
if (this.level == null)
{
@@ -206,5 +208,5 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return "Wrapped{" + this.level.toString() + "@" + this.getDimensionType().getDimensionName() + "}";
}
}
@@ -32,58 +32,58 @@ import net.minecraft.world.level.dimension.DimensionType;
*/
public class DimensionTypeWrapper implements IDimensionTypeWrapper
{
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
private final DimensionType dimensionType;
public DimensionTypeWrapper(DimensionType dimensionType)
{
this.dimensionType = dimensionType;
}
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
{
//first we check if the biome has already been wrapped
if(dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
return dimensionTypeWrapperMap.get(dimensionType);
//if it hasn't been created yet, we create it and save it in the map
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
//we return the newly created wrapper
return dimensionTypeWrapper;
}
public static void clearMap()
{
dimensionTypeWrapperMap.clear();
}
@Override
public String getDimensionName()
{
return dimensionType.effectsLocation().getPath();
}
@Override
public boolean hasCeiling()
{
return dimensionType.hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return dimensionType.hasSkyLight();
}
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
private final DimensionType dimensionType;
public DimensionTypeWrapper(DimensionType dimensionType)
{
this.dimensionType = dimensionType;
}
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
{
//first we check if the biome has already been wrapped
if (dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
return dimensionTypeWrapperMap.get(dimensionType);
//if it hasn't been created yet, we create it and save it in the map
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
//we return the newly created wrapper
return dimensionTypeWrapper;
}
public static void clearMap()
{
dimensionTypeWrapperMap.clear();
}
@Override
public Object getWrappedMcObject()
{
return this.dimensionType;
}
public String getDimensionName()
{
return dimensionType.effectsLocation().getPath();
}
@Override
public boolean hasCeiling()
{
return dimensionType.hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return dimensionType.hasSkyLight();
}
@Override
public Object getWrappedMcObject()
{
return this.dimensionType;
}
@@ -49,41 +49,40 @@ import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
/**
*
* @version 2022-9-16
*/
public class ServerLevelWrapper implements IServerLevelWrapper
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final ConcurrentHashMap<ServerLevel, ServerLevelWrapper>
levelWrapperMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<ServerLevel, ServerLevelWrapper>
levelWrapperMap = new ConcurrentHashMap<>();
public static ServerLevelWrapper getWrapper(ServerLevel level)
{
return levelWrapperMap.computeIfAbsent(level, ServerLevelWrapper::new);
}
public static void closeWrapper(ServerLevel level)
{
levelWrapperMap.remove(level);
}
public static void cleanCheck()
public static ServerLevelWrapper getWrapper(ServerLevel level)
{
return levelWrapperMap.computeIfAbsent(level, ServerLevelWrapper::new);
}
public static void closeWrapper(ServerLevel level)
{
levelWrapperMap.remove(level);
}
public static void cleanCheck()
{
if (!levelWrapperMap.isEmpty())
{
LOGGER.warn(levelWrapperMap.size()+" server levels haven't been freed!");
LOGGER.warn(levelWrapperMap.size() + " server levels haven't been freed!");
levelWrapperMap.clear();
}
}
final ServerLevel level;
ServerBlockDetailMap blockMap = new ServerBlockDetailMap(this);
public ServerLevelWrapper(ServerLevel level)
{
this.level = level;
}
@Nullable
@Override
final ServerLevel level;
ServerBlockDetailMap blockMap = new ServerBlockDetailMap(this);
public ServerLevelWrapper(ServerLevel level)
{
this.level = level;
}
@Nullable
@Override
public IClientLevelWrapper tryGetClientLevelWrapper()
{
MinecraftClientWrapper client = MinecraftClientWrapper.INSTANCE;
@@ -94,99 +93,105 @@ public class ServerLevelWrapper implements IServerLevelWrapper
return ClientLevelWrapper.getWrapper(client.mc.level);
}
@Override
public File getSaveFolder()
{
return level.getChunkSource().getDataStorage().dataFolder;
}
@Override
public DimensionTypeWrapper getDimensionType()
{
return DimensionTypeWrapper.getDimensionTypeWrapper(level.dimensionType());
}
@Override
@Override
public File getSaveFolder()
{
return level.getChunkSource().getDataStorage().dataFolder;
}
@Override
public DimensionTypeWrapper getDimensionType()
{
return DimensionTypeWrapper.getDimensionTypeWrapper(level.dimensionType());
}
@Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; }
@Override
public int getBlockLight(int x, int y, int z)
{
return level.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
}
@Override
public int getSkyLight(int x, int y, int z)
{
return level.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
}
public ServerLevel getLevel()
{
return level;
}
@Override
public boolean hasCeiling()
{
return level.dimensionType().hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return level.dimensionType().hasSkyLight();
}
@Override
public int getHeight()
{
return level.getHeight();
}
@Override
public int getMinHeight()
{
public int getBlockLight(int x, int y, int z)
{
return level.getBrightness(LightLayer.BLOCK, new BlockPos(x, y, z));
}
@Override
public int getSkyLight(int x, int y, int z)
{
return level.getBrightness(LightLayer.SKY, new BlockPos(x, y, z));
}
public ServerLevel getLevel()
{
return level;
}
@Override
public boolean hasCeiling()
{
return level.dimensionType().hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return level.dimensionType().hasSkyLight();
}
@Override
public int getHeight()
{
return level.getHeight();
}
@Override
public int getMinHeight()
{
#if PRE_MC_1_17_1
return 0;
#else
return level.getMinBuildHeight();
return level.getMinBuildHeight();
#endif
}
@Override
public IChunkWrapper tryGetChunk(DhChunkPos pos) {
if (!level.hasChunk(pos.x, pos.z)) return null;
ChunkAccess chunk = level.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
if (chunk == null) return null;
return new ChunkWrapper(chunk, level, this);
}
@Override
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
ChunkSource source = level.getChunkSource();
return source.hasChunk(chunkX, chunkZ);
}
@Override
public IBlockStateWrapper getBlockState(DhBlockPos pos) {
return BlockStateWrapper.fromBlockState(level.getBlockState(McObjectConverter.Convert(pos)));
}
@Override
public IBiomeWrapper getBiome(DhBlockPos pos) {
return BiomeWrapper.getBiomeWrapper(level.getBiome(McObjectConverter.Convert(pos)));
}
@Override
public ServerLevel getWrappedMcObject()
{
return level;
}
@Override
public String toString() {
return "Wrapped{" + level.toString() + "@" + getDimensionType().getDimensionName() + "}";
}
}
@Override
public IChunkWrapper tryGetChunk(DhChunkPos pos)
{
if (!level.hasChunk(pos.x, pos.z)) return null;
ChunkAccess chunk = level.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
if (chunk == null) return null;
return new ChunkWrapper(chunk, level, this);
}
@Override
public boolean hasChunkLoaded(int chunkX, int chunkZ)
{
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
ChunkSource source = level.getChunkSource();
return source.hasChunk(chunkX, chunkZ);
}
@Override
public IBlockStateWrapper getBlockState(DhBlockPos pos)
{
return BlockStateWrapper.fromBlockState(level.getBlockState(McObjectConverter.Convert(pos)));
}
@Override
public IBiomeWrapper getBiome(DhBlockPos pos)
{
return BiomeWrapper.getBiomeWrapper(level.getBiome(McObjectConverter.Convert(pos)));
}
@Override
public ServerLevel getWrappedMcObject()
{
return level;
}
@Override
public String toString()
{
return "Wrapped{" + level.toString() + "@" + getDimensionType().getDimensionName() + "}";
}
}
@@ -96,7 +96,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
public static final ConfigBasedSpamLogger PREF_LOGGER =
new ConfigBasedSpamLogger(LogManager.getLogger("LodWorldGen"),
() -> Config.Client.Advanced.Logging.logWorldGenPerformance.get(),1);
() -> Config.Client.Advanced.Logging.logWorldGenPerformance.get(), 1);
public static final ConfigBasedLogger EVENT_LOGGER =
new ConfigBasedLogger(LogManager.getLogger("LodWorldGen"),
() -> Config.Client.Advanced.Logging.logWorldGenEvent.get());
@@ -128,7 +128,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
public PerfCalculator()
{
for(int i = 0; i < 11; i++)
for (int i = 0; i < 11; i++)
{
times.add(new Rolling(SIZE));
}
@@ -140,7 +140,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
String name = e.name;
int index = Arrays.asList(TIME_NAMES).indexOf(name);
if(index == -1) continue;
if (index == -1) continue;
times.get(index).add(e.timeNs);
}
times.get(0).add(event.getTotalTimeNs());
@@ -156,6 +156,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
return sb.toString();
}
}
private final IDhServerLevel serverlevel;
@@ -177,9 +178,9 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
public int unknownExceptionCount = 0;
public long lastExceptionTriggerTime = 0;
private AtomicReference<RegionFileStorageExternalCache> regionFileStorageCacheRef = new AtomicReference<>();
public RegionFileStorageExternalCache getOrCreateRegionFileCache(RegionFileStorage storage)
{
RegionFileStorageExternalCache cache = regionFileStorageCacheRef.get();
@@ -197,16 +198,19 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
public static ThreadLocal<Boolean> isDistantGeneratorThread = new ThreadLocal<>();
public static ThreadLocal<Object> onDistantGenerationMixinData = new ThreadLocal<>();
public static boolean isCurrentThreadDistantGeneratorThread() { return (isDistantGeneratorThread.get() != null); }
public static void putDistantGenerationMixinData(Object data) {
public static void putDistantGenerationMixinData(Object data)
{
LodUtil.assertTrue(isCurrentThreadDistantGeneratorThread());
onDistantGenerationMixinData.set(data);
}
public static Object getDistantGenerationMixinData() {
public static Object getDistantGenerationMixinData()
{
LodUtil.assertTrue(isCurrentThreadDistantGeneratorThread());
return onDistantGenerationMixinData.get();
}
public static void clearDistantGenerationMixinData() {
public static void clearDistantGenerationMixinData()
{
LodUtil.assertTrue(isCurrentThreadDistantGeneratorThread());
onDistantGenerationMixinData.remove();
}
@@ -218,19 +222,22 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
//==============//
// constructors //
//==============//
public static ImmutableMap<EDhApiWorldGenerationStep, Integer> BorderNeeded;
public static int MaxBorderNeeded;
static
{
DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
boolean isTerraFirmaCraft = false;
try {
try
{
Class.forName("net.dries007.tfc.world.TFCChunkGenerator");
isTerraFirmaCraft = true;
} catch (ClassNotFoundException e) {
}
catch (ClassNotFoundException e)
{
//Ignore
}
EVENT_LOGGER.info("DH TerraFirmaCraft detection: " + isTerraFirmaCraft);
@@ -265,18 +272,18 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
if (generator.getClass().toString().equals("class com.terraforged.mod.chunk.TFChunkGenerator"))
{
EVENT_LOGGER.info("TerraForge Chunk Generator detected: ["+generator.getClass()+"], Distant Generation will try its best to support it.");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to ["+EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY+"].");
EVENT_LOGGER.info("TerraForge Chunk Generator detected: [" + generator.getClass() + "], Distant Generation will try its best to support it.");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
}
else if (generator.getClass().toString().equals("class net.dries007.tfc.world.TFCChunkGenerator"))
{
EVENT_LOGGER.info("TerraFirmaCraft Chunk Generator detected: ["+generator.getClass()+"], Distant Generation will try its best to support it.");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to ["+ EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY +"].");
EVENT_LOGGER.info("TerraFirmaCraft Chunk Generator detected: [" + generator.getClass() + "], Distant Generation will try its best to support it.");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
}
else
{
EVENT_LOGGER.warn("Unknown Chunk Generator detected: ["+generator.getClass()+"], Distant Generation May Fail!");
EVENT_LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to ["+EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY+"].");
EVENT_LOGGER.warn("Unknown Chunk Generator detected: [" + generator.getClass() + "], Distant Generation May Fail!");
EVENT_LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
}
}
@@ -351,27 +358,29 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
}
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER) {
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER)
{
EVENT_LOGGER.error("Too many exceptions in Batching World Generator! Disabling the generator.");
unknownExceptionCount = 0;
Config.Client.Advanced.WorldGenerator.enableDistantGeneration.set(false);
}
}
private static ProtoChunk EmptyChunk(ServerLevel level, ChunkPos chunkPos) {
private static ProtoChunk EmptyChunk(ServerLevel level, ChunkPos chunkPos)
{
return new ProtoChunk(chunkPos, UpgradeData.EMPTY
#if POST_MC_1_17_1, level #endif
#if POST_MC_1_18_2, level.registryAccess().registryOrThrow(
#if POST_MC_1_17_1 , level #endif
#if POST_MC_1_18_2 , level.registryAccess().registryOrThrow(
#if PRE_MC_1_19_4
Registry.BIOME_REGISTRY
Registry.BIOME_REGISTRY
#else
Registries.BIOME
Registries.BIOME
#endif
), null #endif
);
}
public ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, WorldGenLevelLightEngine lightEngine)
{
ServerLevel level = this.params.level;
@@ -389,7 +398,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
catch (Exception e)
{
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk "+chunkPos+". Error: "+e.getMessage(), e);
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e);
}
if (chunkData == null)
@@ -400,34 +409,36 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
try
{
LOAD_LOGGER.info("DistantHorizons: Loading chunk "+chunkPos+" from disk.");
LOAD_LOGGER.info("DistantHorizons: Loading chunk " + chunkPos + " from disk.");
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
}
catch (Exception e)
{
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk "+chunkPos+". Returning an empty chunk. Error: "+e.getMessage(), e);
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Returning an empty chunk. Error: " + e.getMessage(), e);
return EmptyChunk(level, chunkPos);
}
}
}
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border) {
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border)
{
return new ArrayGridList<>(total, border, total.gridSize - border);
}
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) {
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step)
{
return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step));
}
public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException
{
EVENT_LOGGER.debug("Lod Generate Event: "+genEvent.minPos);
EVENT_LOGGER.debug("Lod Generate Event: " + genEvent.minPos);
ArrayGridList<ChunkWrapper> chunkWrapperList;
DhLitWorldGenRegion region;
WorldGenLevelLightEngine lightEngine;
LightGetterAdaptor adaptor;
int borderSize = MaxBorderNeeded;
int refSize = genEvent.size + borderSize * 2;
int refPosX = genEvent.minPos.x - borderSize;
@@ -462,12 +473,12 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
return target;
};
totalChunks = new ArrayGridList<>(refSize, (x,z) -> generator.generate(x + refPosX,z + refPosZ));
totalChunks = new ArrayGridList<>(refSize, (x, z) -> generator.generate(x + refPosX, z + refPosZ));
genEvent.refreshTimeout();
region = new DhLitWorldGenRegion(params.level, lightEngine, totalChunks,
ChunkStatus.STRUCTURE_STARTS, refSize/2, generator);
ChunkStatus.STRUCTURE_STARTS, refSize / 2, generator);
adaptor.setRegion(region);
genEvent.threadedParam.makeStructFeat(region, params);
@@ -478,7 +489,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
ChunkAccess chunk = totalChunks.get(x, z);
if (chunk != null)
{
chunkWrapperList.set(x,z, new ChunkWrapper(chunk, region, null));
chunkWrapperList.set(x, z, new ChunkWrapper(chunk, region, null));
}
});
@@ -488,7 +499,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
catch (StepStructureStart.StructStartCorruptedException f)
{
genEvent.threadedParam.markAsInvalid();
throw (RuntimeException)f.getCause();
throw (RuntimeException) f.getCause();
}
ArrayGridList<ChunkWrapper> finalGenChunks = GetCutoutFrom(chunkWrapperList, borderSize);
@@ -498,7 +509,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
ChunkWrapper wrappedChunk = finalGenChunks.get(offsetX, offsetY);
ChunkAccess target = wrappedChunk.getChunk();
if (target instanceof LevelChunk)
if (target instanceof LevelChunk)
{
#if MC_1_16_5 || MC_1_17_1
((LevelChunk) target).setLoaded(true);
@@ -552,12 +563,13 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
}
public void generateDirect(GenerationEvent genEvent, ArrayGridList<ChunkWrapper> chunksToGenerate, int border,
EDhApiWorldGenerationStep step, DhLitWorldGenRegion region) throws InterruptedException
public void generateDirect(
GenerationEvent genEvent, ArrayGridList<ChunkWrapper> chunksToGenerate, int border,
EDhApiWorldGenerationStep step, DhLitWorldGenRegion region) throws InterruptedException
{
if (Thread.interrupted())
{
return;
return;
}
try
@@ -677,7 +689,11 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
}
public interface EmptyChunkGenerator { ChunkAccess generate(int x, int z); }
public interface EmptyChunkGenerator
{
ChunkAccess generate(int x, int z);
}
@Override
public int getEventCount() { return this.generationEventList.size(); }
@@ -685,7 +701,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
@Override
public void stop()
{
EVENT_LOGGER.info(BatchGenerationEnvironment.class.getSimpleName()+" shutting down...");
EVENT_LOGGER.info(BatchGenerationEnvironment.class.getSimpleName() + " shutting down...");
EVENT_LOGGER.info("Canceling in progress generation event futures...");
Iterator<GenerationEvent> iter = this.generationEventList.iterator();
@@ -710,7 +726,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
}
EVENT_LOGGER.info(BatchGenerationEnvironment.class.getSimpleName()+" shutdown complete.");
EVENT_LOGGER.info(BatchGenerationEnvironment.class.getSimpleName() + " shutdown complete.");
}
@Override
@@ -735,7 +751,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
if (Thread.interrupted())
{
throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName()+" task interrupted.");
throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName() + " task interrupted.");
}
}
@@ -52,8 +52,9 @@ public final class GenerationEvent
public GenerationEvent(DhChunkPos minPos, int size, BatchGenerationEnvironment generationGroup,
EDhApiWorldGenerationStep targetGenerationStep, Consumer<IChunkWrapper> resultConsumer)
public GenerationEvent(
DhChunkPos minPos, int size, BatchGenerationEnvironment generationGroup,
EDhApiWorldGenerationStep targetGenerationStep, Consumer<IChunkWrapper> resultConsumer)
{
this.inQueueTime = System.nanoTime();
this.id = generationFutureDebugIDs++;
@@ -91,7 +92,9 @@ public final class GenerationEvent
//LOGGER.info("generating [{}]", event.minPos);
genEnvironment.generateLodFromList(generationEvent);
}
catch (InterruptedException ignored) { }
catch (InterruptedException ignored)
{
}
finally
{
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
@@ -144,6 +147,6 @@ public final class GenerationEvent
}
@Override
public String toString() { return this.id+":"+this.size+"@"+this.minPos+"("+this.targetGenerationStep +")"; }
public String toString() { return this.id + ":" + this.size + "@" + this.minPos + "(" + this.targetGenerationStep + ")"; }
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
import com.mojang.datafixers.DataFixer;
@@ -76,8 +76,8 @@ public final class GlobalParameters
public GlobalParameters(IDhServerLevel lodLevel)
{
this.lodLevel = lodLevel;
level = ((ServerLevelWrapper)lodLevel.getServerLevelWrapper()).getWrappedMcObject();
level = ((ServerLevelWrapper) lodLevel.getServerLevelWrapper()).getWrappedMcObject();
lightEngine = (ThreadedLevelLightEngine) level.getLightEngine();
MinecraftServer server = level.getServer();
WorldData worldData = server.getWorldData();
@@ -103,4 +103,5 @@ public final class GlobalParameters
randomState = level.getChunkSource().randomState();
#endif
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
@@ -34,7 +34,9 @@ public class Rolling
this.size = size;
samples = new double[size];
for (int i = 0; i < size; i++)
{
samples[i] = 0d;
}
}
public void add(double x)
@@ -48,6 +50,7 @@ public class Rolling
public double getAverage()
{
return size==0 ? 0 : total / size;
return size == 0 ? 0 : total / size;
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
@@ -81,7 +81,7 @@ public final class ThreadedParameters
public void makeStructFeat(WorldGenLevel genLevel, GlobalParameters param)
{
#if PRE_MC_1_19_4
structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel #if POST_MC_1_18_2, structCheck #endif);
structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel #if POST_MC_1_18_2 , structCheck #endif );
#else
structFeat = new WorldGenStructFeatManager(param.worldOptions, genLevel, structCheck);
#endif
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGeneratio
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
@@ -89,21 +90,21 @@ public class ChunkLoader
private static final String BLOCK_TICKS_TAG_PRE18 = "TileTicks";
private static final String FLUID_TICKS_TAG_PRE18 = "LiquidTicks";
private static final ConfigBasedLogger LOGGER = BatchGenerationEnvironment.LOAD_LOGGER;
#if POST_MC_1_18_2
private static BlendingData readBlendingData(CompoundTag chunkData)
{
BlendingData blendingData = null;
if (chunkData.contains("blending_data", 10))
{
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({"unchecked", "rawtypes"})
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
}
return blendingData;
}
#endif
private static LevelChunkSection[] readSections(LevelAccessor level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
{
#if POST_MC_1_18_2
@@ -116,8 +117,8 @@ public class ChunkLoader
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
#elif PRE_MC_1_19_2
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
#else
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
@@ -125,26 +126,27 @@ public class ChunkLoader
#endif
int i = #if PRE_MC_1_17_1 16; #else level.getSectionsCount(); #endif
LevelChunkSection[] chunkSections = new LevelChunkSection[i];
boolean isLightOn = chunkData.getBoolean("isLightOn");
boolean hasSkyLight = level.dimensionType().hasSkyLight();
ListTag tagSections = chunkData.getList("Sections", 10);
if (tagSections.isEmpty()) tagSections = chunkData.getList("sections", 10);
for (int j = 0; j < tagSections.size(); ++j)
{
CompoundTag tagSection = tagSections.getCompound(j);
int sectionYPos = tagSection.getByte("Y");
#if PRE_MC_1_18_2
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12)) {
if (tagSection.contains("Palette", 9) && tagSection.contains("BlockStates", 12))
{
LevelChunkSection levelChunkSection = new LevelChunkSection(sectionYPos << 4);
levelChunkSection.getStates().read(tagSection.getList("Palette", 10),
tagSection.getLongArray("BlockStates"));
levelChunkSection.recalcBlockCounts();
if (!levelChunkSection.isEmpty())
chunkSections[#if PRE_MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif]
= levelChunkSection;
chunkSections[#if PRE_MC_1_17_1 sectionYPos #else level.getSectionIndexFromSectionY(sectionYPos) #endif ]
= levelChunkSection;
}
#else
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
@@ -156,7 +158,7 @@ public class ChunkLoader
#else
PalettedContainer<Holder<Biome>> biomeContainer;
#endif
blockStateContainer = tagSection.contains("block_states", 10)
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
@@ -177,18 +179,18 @@ public class ChunkLoader
#endif
}
#endif
if (!isLightOn) continue;
if (tagSection.contains("BlockLight", 7))
lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, sectionYPos),
new DataLayer(tagSection.getByteArray("BlockLight")) #if PRE_MC_1_20_1, true #endif);
new DataLayer(tagSection.getByteArray("BlockLight")) #if PRE_MC_1_20_1 , true #endif );
if (hasSkyLight && tagSection.contains("SkyLight", 7))
lightEngine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, sectionYPos),
new DataLayer(tagSection.getByteArray("SkyLight")) #if PRE_MC_1_20_1, true #endif);
new DataLayer(tagSection.getByteArray("SkyLight")) #if PRE_MC_1_20_1 , true #endif );
}
return chunkSections;
}
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
{
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
@@ -200,7 +202,7 @@ public class ChunkLoader
}
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
}
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
{
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
@@ -213,16 +215,17 @@ public class ChunkLoader
}
}
}
public static ChunkStatus.ChunkType readChunkType(CompoundTag tagLevel)
{
ChunkStatus chunkStatus = ChunkStatus.byName(tagLevel.getString("Status"));
if (chunkStatus != null) {
if (chunkStatus != null)
{
return chunkStatus.getChunkType();
}
return ChunkStatus.ChunkType.PROTOCHUNK;
}
public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
{
#if PRE_MC_1_18_2
@@ -230,13 +233,14 @@ public class ChunkLoader
#else
CompoundTag tagLevel = chunkData;
#endif
ChunkPos actualPos = new ChunkPos(tagLevel.getInt("xPos"), tagLevel.getInt("zPos"));
if (!Objects.equals(chunkPos, actualPos)) {
if (!Objects.equals(chunkPos, actualPos))
{
LOGGER.error("Chunk file at {} is in the wrong location; Ignoring. (Expected {}, got {})", chunkPos, chunkPos, actualPos);
return null;
}
ChunkStatus.ChunkType chunkType = readChunkType(tagLevel);
#if PRE_MC_1_18_2
if (chunkType != ChunkStatus.ChunkType.LEVELCHUNK)
@@ -251,31 +255,31 @@ public class ChunkLoader
return null;
#endif
#endif
long inhabitedTime = tagLevel.getLong("InhabitedTime");
//================== Read params for making the LevelChunk ==================
UpgradeData upgradeData = tagLevel.contains(TAG_UPGRADE_DATA, 10)
? new UpgradeData(tagLevel.getCompound(TAG_UPGRADE_DATA)#if POST_MC_1_17_1, level #endif)
? new UpgradeData(tagLevel.getCompound(TAG_UPGRADE_DATA)#if POST_MC_1_17_1 , level #endif )
: UpgradeData.EMPTY;
boolean isLightOn = tagLevel.getBoolean("isLightOn");
if (isLightOn) lightEngine.retainData(chunkPos, true);
#if PRE_MC_1_18_2
ChunkBiomeContainer chunkBiomeContainer = new ChunkBiomeContainer(
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if POST_MC_1_17_1, level #endif,
level.getLevel().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY)#if POST_MC_1_17_1 , level #endif ,
chunkPos, level.getLevel().getChunkSource().getGenerator().getBiomeSource(),
tagLevel.contains("Biomes", 11) ? tagLevel.getIntArray("Biomes") : null);
TickList<Block> blockTicks = tagLevel.contains(BLOCK_TICKS_TAG_PRE18, 9)
? ChunkTickList.create(tagLevel.getList(BLOCK_TICKS_TAG_PRE18, 10), Registry.BLOCK::getKey, Registry.BLOCK::get)
: new ProtoTickList<Block>(block -> (block == null || block.defaultBlockState().isAir()), chunkPos,
tagLevel.getList("ToBeTicked", 9)#if POST_MC_1_17_1, level #endif);
tagLevel.getList("ToBeTicked", 9)#if POST_MC_1_17_1 , level #endif );
TickList<Fluid> fluidTicks = tagLevel.contains(FLUID_TICKS_TAG_PRE18, 9)
? ChunkTickList.create(tagLevel.getList(FLUID_TICKS_TAG_PRE18, 10), Registry.FLUID::getKey, Registry.FLUID::get)
: new ProtoTickList<Fluid>(fluid -> (fluid == null || fluid == Fluids.EMPTY), chunkPos,
tagLevel.getList("LiquidsToBeTicked", 9)#if POST_MC_1_17_1, level #endif);
tagLevel.getList("LiquidsToBeTicked", 9)#if POST_MC_1_17_1 , level #endif );
#else
#if PRE_MC_1_19_4
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(tagLevel.getList(BLOCK_TICKS_TAG_18, 10),
@@ -289,15 +293,15 @@ public class ChunkLoader
string -> BuiltInRegistries.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
#endif
#endif
LevelChunkSection[] levelChunkSections = readSections(level, lightEngine, chunkPos, tagLevel);
// ====================== Make the chunk =========================
#if PRE_MC_1_18_2
LevelChunk chunk = new LevelChunk((Level) level.getLevel(), chunkPos, chunkBiomeContainer, upgradeData, blockTicks,
fluidTicks, inhabitedTime, levelChunkSections, null);
#else
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks,
fluidTicks, inhabitedTime, levelChunkSections, null, blendingData);
#endif
@@ -307,10 +311,11 @@ public class ChunkLoader
readPostPocessings(chunk, chunkData);
return chunk;
}
private static void logErrors(ChunkPos chunkPos, int i, String string)
{
LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string);
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
import java.lang.invoke.MethodHandles;
@@ -69,29 +69,33 @@ public class DhLitWorldGenRegion extends WorldGenRegion
#if PRE_MC_1_18_2
private ChunkPos overrideCenterPos = null;
public void setOverrideCenter(ChunkPos pos) {overrideCenterPos = pos;}
#if PRE_MC_1_17_1
@Override
public int getCenterX() {
return overrideCenterPos==null ? super.getCenterX() : overrideCenterPos.x;
}
@Override
public int getCenterZ() {
return overrideCenterPos==null ? super.getCenterX() : overrideCenterPos.z;
}
#else
@Override
public ChunkPos getCenter() {
return overrideCenterPos==null ? super.getCenter() : overrideCenterPos;
}
#endif
public void setOverrideCenter(ChunkPos pos) { overrideCenterPos = pos; }
#if PRE_MC_1_17_1
@Override
public int getCenterX()
{
return overrideCenterPos==null ? super.getCenterX() : overrideCenterPos.x;
}
@Override
public int getCenterZ()
{
return overrideCenterPos==null ? super.getCenterX() : overrideCenterPos.z;
}
#else
@Override
public ChunkPos getCenter()
{
return overrideCenterPos == null ? super.getCenter() : overrideCenterPos;
}
#endif
public DhLitWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
#endif
public DhLitWorldGenRegion(
ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
List<ChunkAccess> chunkList, ChunkStatus chunkStatus, int writeRadius,
BatchGenerationEnvironment.EmptyChunkGenerator generator)
{
super(serverLevel, chunkList #if POST_MC_1_17_1, chunkStatus, writeRadius #endif);
super(serverLevel, chunkList #if POST_MC_1_17_1 , chunkStatus, writeRadius #endif );
this.firstPos = chunkList.get(0).getPos();
this.generator = generator;
this.light = lightEngine;
@@ -99,43 +103,47 @@ public class DhLitWorldGenRegion extends WorldGenRegion
this.cache = chunkList;
this.size = Mth.floor(Math.sqrt(chunkList.size()));
}
#if POST_MC_1_17_1
// Bypass BCLib mixin overrides.
@Override
public boolean ensureCanWrite(BlockPos blockPos)
@Override
public boolean ensureCanWrite(BlockPos blockPos)
{
int i = SectionPos.blockToSectionCoord(blockPos.getX());
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
ChunkPos chunkPos = this.getCenter();
ChunkAccess center = this.getChunk(chunkPos.x, chunkPos.z);
int k = Math.abs(chunkPos.x - i);
int l = Math.abs(chunkPos.z - j);
if (k > this.writeRadius || l > this.writeRadius) {
return false;
}
int i = SectionPos.blockToSectionCoord(blockPos.getX());
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
ChunkPos chunkPos = this.getCenter();
ChunkAccess center = this.getChunk(chunkPos.x, chunkPos.z);
int k = Math.abs(chunkPos.x - i);
int l = Math.abs(chunkPos.z - j);
if (k > this.writeRadius || l > this.writeRadius)
{
return false;
}
#if POST_MC_1_18_2
if (center.isUpgrading()) {
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight()) {
return false;
}
}
if (center.isUpgrading())
{
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight())
{
return false;
}
}
#endif
return true;
}
return true;
}
#endif
// TODO Check this
// @Override
// public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
// StructureFeature<?> structureFeature) {
// return structFeat.startsForFeature(sectionPos, structureFeature);
// }
// Skip updating the related tile entities
@Override
public boolean setBlock(BlockPos blockPos, BlockState blockState, int i, int j) {
public boolean setBlock(BlockPos blockPos, BlockState blockState, int i, int j)
{
ChunkAccess chunkAccess = this.getChunk(blockPos);
if (chunkAccess instanceof LevelChunk)
return true;
@@ -146,104 +154,121 @@ public class DhLitWorldGenRegion extends WorldGenRegion
// this.getChunk(blockPos).markPosForPostprocessing(blockPos);
return true;
}
// Skip Dropping the item on destroy
@Override
public boolean destroyBlock(BlockPos blockPos, boolean bl, @Nullable Entity entity, int i) {
public boolean destroyBlock(BlockPos blockPos, boolean bl, @Nullable Entity entity, int i)
{
BlockState blockState = this.getBlockState(blockPos);
if (blockState.isAir()) {
if (blockState.isAir())
{
return false;
}
return this.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3, i);
}
// Skip BlockEntity stuff. It aren't really needed
@Override
public BlockEntity getBlockEntity(BlockPos blockPos) {
public BlockEntity getBlockEntity(BlockPos blockPos)
{
BlockState blockState = this.getBlockState(blockPos);
// This is a bypass for the spawner block since MC complains about not having it
#if POST_MC_1_17_1
if (blockState.getBlock() instanceof SpawnerBlock) {
if (blockState.getBlock() instanceof SpawnerBlock)
{
return ((EntityBlock) blockState.getBlock()).newBlockEntity(blockPos, blockState);
} else return null;
}
else return null;
#else
if (blockState.getBlock() instanceof SpawnerBlock) {
return ((EntityBlock) blockState.getBlock()).newBlockEntity(this);
} else return null;
#endif
}
// Skip BlockEntity stuff. It aren't really needed
@Override
public boolean addFreshEntity(Entity entity) {
public boolean addFreshEntity(Entity entity)
{
return true;
}
// Allays have empty chunks even if it's outside the worldGenRegion
// @Override
// public boolean hasChunk(int i, int j) {
// return true;
// }
// Override to ensure no other mod mixins cause skipping the overrided
// getChunk(...)
@Override
public ChunkAccess getChunk(int i, int j) {
public ChunkAccess getChunk(int i, int j)
{
return this.getChunk(i, j, ChunkStatus.EMPTY);
}
// Override to ensure no other mod mixins cause skipping the overrided
// getChunk(...)
@Override
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus) {
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus)
{
return this.getChunk(i, j, chunkStatus, true);
}
// Use this instead of super.getChunk() to bypass C2ME concurrency checks
private ChunkAccess superGetChunk(int x, int z, ChunkStatus cs) {
private ChunkAccess superGetChunk(int x, int z, ChunkStatus cs)
{
int k = x - firstPos.x;
int l = z - firstPos.z;
return cache.get(k + l * size);
}
// Use this instead of super.hasChunk() to bypass C2ME concurrency checks
public boolean superHasChunk(int x, int z) {
public boolean superHasChunk(int x, int z)
{
int k = x - firstPos.x;
int l = z - firstPos.z;
return l >= 0 && l < size && k >= 0 && k < size;
}
// Allow creating empty chunks even if it's outside the worldGenRegion
@Override
@Nullable
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl) {
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl)
{
ChunkAccess chunk = getChunkAccess(i, j, chunkStatus, bl);
if (chunk instanceof LevelChunk) {
chunk = new ImposterProtoChunk((LevelChunk) chunk #if POST_MC_1_18_2, true #endif);
if (chunk instanceof LevelChunk)
{
chunk = new ImposterProtoChunk((LevelChunk) chunk #if POST_MC_1_18_2 , true #endif );
}
return chunk;
}
private static ChunkStatus debugTriggeredForStatus = null;
private ChunkAccess getChunkAccess(int i, int j, ChunkStatus chunkStatus, boolean bl) {
private ChunkAccess getChunkAccess(int i, int j, ChunkStatus chunkStatus, boolean bl)
{
ChunkAccess chunk = superHasChunk(i, j) ? superGetChunk(i, j, ChunkStatus.EMPTY) : null;
if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus)) {
if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus))
{
return chunk;
}
if (!bl)
return null;
if (chunk == null) {
if (chunk == null)
{
chunk = chunkMap.get(ChunkPos.asLong(i, j));
if (chunk == null) {
if (chunk == null)
{
chunk = generator.generate(i, j);
if (chunk == null)
throw new NullPointerException("The provided generator should not return null!");
chunkMap.put(ChunkPos.asLong(i, j), chunk);
}
}
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus)
{
LOGGER.info("WorldGen requiring " + chunkStatus
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
debugTriggeredForStatus = chunkStatus;
@@ -265,7 +290,8 @@ public class DhLitWorldGenRegion extends WorldGenRegion
/** Overriding allows us to use our own lighting engine */
@Override
public boolean canSeeSky(BlockPos blockPos) {
public boolean canSeeSky(BlockPos blockPos)
{
return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
}
@@ -273,8 +299,9 @@ public class DhLitWorldGenRegion extends WorldGenRegion
{
return calculateBlockTint(blockPos, colorResolver);
}
private Biome _getBiome(BlockPos pos) {
private Biome _getBiome(BlockPos pos)
{
#if POST_MC_1_18_2
return getBiome(pos).value();
#else
@@ -307,5 +334,5 @@ public class DhLitWorldGenRegion extends WorldGenRegion
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
@@ -32,35 +32,41 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
import net.minecraft.world.level.chunk.LightChunk;
#endif
public class LightGetterAdaptor implements LightChunkGetter {
public class LightGetterAdaptor implements LightChunkGetter
{
private final BlockGetter heightGetter;
public DhLitWorldGenRegion genRegion = null;
final boolean shouldReturnNull;
public LightGetterAdaptor(BlockGetter heightAccessor) {
public LightGetterAdaptor(BlockGetter heightAccessor)
{
this.heightGetter = heightAccessor;
shouldReturnNull = ModAccessorInjector.INSTANCE.get(IStarlightAccessor.class) != null;
}
public void setRegion(DhLitWorldGenRegion region) {
public void setRegion(DhLitWorldGenRegion region)
{
genRegion = region;
}
@Override
public #if PRE_MC_1_20_1 BlockGetter #else LightChunk #endif getChunkForLighting(int chunkX, int chunkZ) {
public #if PRE_MC_1_20_1 BlockGetter #else LightChunk #endif getChunkForLighting(int chunkX, int chunkZ)
{
if (genRegion == null)
throw new IllegalStateException("World Gen region has not been set!");
// May be null
return genRegion.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, false);
}
@Override
public BlockGetter getLevel() {
public BlockGetter getLevel()
{
return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
}
#if POST_MC_1_17_1
public LevelHeightAccessor getLevelHeightAccessor() {
public LevelHeightAccessor getLevelHeightAccessor()
{
return heightGetter;
}
#endif
@@ -14,43 +14,44 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.ConcurrentLinkedQueue;
public class RegionFileStorageExternalCache implements AutoCloseable
public class RegionFileStorageExternalCache implements AutoCloseable
{
public final RegionFileStorage storage;
public static final int MAX_CACHE_SIZE = 16;
@Override
public void close() throws IOException
{
RegionFileCache cache;
while ((cache = this.regionFileCache.poll()) != null)
public final RegionFileStorage storage;
public static final int MAX_CACHE_SIZE = 16;
@Override
public void close() throws IOException
{
RegionFileCache cache;
while ((cache = this.regionFileCache.poll()) != null)
{
cache.file.close();
}
}
static class RegionFileCache
{
public final long pos;
public final RegionFile file;
public RegionFileCache(long pos, RegionFile file)
{
this.pos = pos;
this.file = file;
}
}
public ConcurrentLinkedQueue<RegionFileCache> regionFileCache = new ConcurrentLinkedQueue<>();
public RegionFileStorageExternalCache(RegionFileStorage storage) { this.storage = storage; }
@Nullable
public RegionFile getRegionFile(ChunkPos pos) throws IOException
cache.file.close();
}
}
static class RegionFileCache
{
public final long pos;
public final RegionFile file;
public RegionFileCache(long pos, RegionFile file)
{
this.pos = pos;
this.file = file;
}
}
public ConcurrentLinkedQueue<RegionFileCache> regionFileCache = new ConcurrentLinkedQueue<>();
public RegionFileStorageExternalCache(RegionFileStorage storage) { this.storage = storage; }
@Nullable
public RegionFile getRegionFile(ChunkPos pos) throws IOException
{
long posLong = ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ());
RegionFile rFile = null;
// Check vanilla cache
int retryCount = 0;
int maxRetryCount = 8;
@@ -79,8 +80,10 @@ public class RegionFileStorageExternalCache implements AutoCloseable
{
Thread.sleep(250);
}
catch (InterruptedException ignored) { }
#endif
catch (InterruptedException ignored)
{
}
#endif
}
}
@@ -94,7 +97,7 @@ public class RegionFileStorageExternalCache implements AutoCloseable
{
return rFile;
}
// Then check our custom cache
for (RegionFileCache cache : this.regionFileCache)
{
@@ -134,8 +137,8 @@ public class RegionFileStorageExternalCache implements AutoCloseable
}
@Nullable
public CompoundTag read(ChunkPos pos) throws IOException
@Nullable
public CompoundTag read(ChunkPos pos) throws IOException
{
RegionFile file = getRegionFile(pos);
if (file == null)
@@ -158,5 +161,5 @@ public class RegionFileStorageExternalCache implements AutoCloseable
return null;
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
import net.minecraft.world.level.lighting.*;
@@ -34,249 +34,300 @@ import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.LevelChunkSection;
import org.jetbrains.annotations.PropertyKey;
public class WorldGenLevelLightEngine extends LevelLightEngine {
public class WorldGenLevelLightEngine extends LevelLightEngine
{
public static final int MAX_SOURCE_LEVEL = 15;
public static final int LIGHT_SECTION_PADDING = 1;
#if POST_MC_1_17_1
protected final LevelHeightAccessor levelHeightAccessor;
public static final int LIGHT_SECTION_PADDING = 1;
#if POST_MC_1_17_1
protected final LevelHeightAccessor levelHeightAccessor;
#endif
#if PRE_MC_1_20_1
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
#else
@Nullable
public final LightEngine<?, ?> blockEngine;
@Nullable
public final LightEngine<?, ?> skyEngine;
#if PRE_MC_1_20_1
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
#else
@Nullable
public final LightEngine<?, ?> blockEngine;
@Nullable
public final LightEngine<?, ?> skyEngine;
#endif
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
super(genRegion, false, false);
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion)
{
super(genRegion, false, false);
#if POST_MC_1_17_1
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
#endif
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
#if PRE_MC_1_20_1
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i)
{
if (this.blockEngine != null)
{
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2)
{
if (this.blockEngine != null && this.skyEngine != null)
{
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0)
{
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null)
{
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null)
{
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl)
{
if (this.blockEngine != null)
{
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null)
{
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
#if PRE_MC_1_20_1
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
if (this.blockEngine != null) {
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2) {
if (this.blockEngine != null && this.skyEngine != null) {
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0) {
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null) {
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null) {
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
#else
@Override
public int runLightUpdates() {
int $$0 = 0;
if (this.blockEngine != null) {
$$0 += this.blockEngine.runLightUpdates();
}
if (this.skyEngine != null) {
$$0 += this.skyEngine.runLightUpdates();
}
return $$0;
}
@Override
public void setLightEnabled(ChunkPos $$0, boolean $$1) {
if (this.blockEngine != null) {
this.blockEngine.setLightEnabled($$0, $$1);
}
if (this.skyEngine != null) {
this.skyEngine.setLightEnabled($$0, $$1);
}
}
@Override
public void propagateLightSources(ChunkPos arg) {
if (this.skyEngine != null) {
this.skyEngine.propagateLightSources(arg);
}
if (this.blockEngine != null) {
this.blockEngine.propagateLightSources(arg);
}
}
public boolean lightOnInSection(SectionPos $$0) {
long $$1 = $$0.asLong();
return this.blockEngine == null
/*Note: Somehow vanilla access the protected 'storage' field from the LevelLightEngine class... we're using mixin to do this.*/
|| this.blockEngine.storage.lightOnInSection($$1) && (this.skyEngine == null || this.skyEngine.storage.lightOnInSection($$1));
}
#else
@Override
public int runLightUpdates()
{
int $$0 = 0;
if (this.blockEngine != null)
{
$$0 += this.blockEngine.runLightUpdates();
}
if (this.skyEngine != null)
{
$$0 += this.skyEngine.runLightUpdates();
}
return $$0;
}
@Override
public void setLightEnabled(ChunkPos $$0, boolean $$1)
{
if (this.blockEngine != null)
{
this.blockEngine.setLightEnabled($$0, $$1);
}
if (this.skyEngine != null)
{
this.skyEngine.setLightEnabled($$0, $$1);
}
}
@Override
public void propagateLightSources(ChunkPos arg)
{
if (this.skyEngine != null)
{
this.skyEngine.propagateLightSources(arg);
}
if (this.blockEngine != null)
{
this.blockEngine.propagateLightSources(arg);
}
}
public boolean lightOnInSection(SectionPos $$0)
{
long $$1 = $$0.asLong();
return this.blockEngine == null
/*Note: Somehow vanilla access the protected 'storage' field from the LevelLightEngine class... we're using mixin to do this.*/
|| this.blockEngine.storage.lightOnInSection($$1) && (this.skyEngine == null || this.skyEngine.storage.lightOnInSection($$1));
}
#endif
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer #if PRE_MC_1_20_1, boolean bl #endif) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine != null) {
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer #if PRE_MC_1_20_1, bl #endif);
}
} else if (this.skyEngine != null) {
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer #if PRE_MC_1_20_1, bl #endif);
}
}
@Override
public void checkBlock(BlockPos blockPos) {
if (this.blockEngine != null) {
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null) {
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public boolean hasLightWork() {
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i <
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer #if PRE_MC_1_20_1 , boolean bl #endif )
{
if (lightLayer == LightLayer.BLOCK)
{
if (this.blockEngine != null)
{
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer #if PRE_MC_1_20_1 , bl #endif );
}
}
else if (this.skyEngine != null)
{
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer #if PRE_MC_1_20_1 , bl #endif );
}
}
@Override
public void checkBlock(BlockPos blockPos)
{
if (this.blockEngine != null)
{
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null)
{
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public boolean hasLightWork()
{
if (this.skyEngine != null && this.skyEngine.hasLightWork())
{
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl)
{
if (this.blockEngine != null)
{
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null)
{
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer)
{
if (lightLayer == LightLayer.BLOCK)
{
if (this.blockEngine == null)
{
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null)
{
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public int getRawBrightness(BlockPos blockPos, int i)
{
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate)
{
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i <
#if POST_MC_1_17_1
chunkAccess.getSectionsCount()
chunkAccess.getSectionsCount()
#else
16
#endif
; ++i) {
LevelChunkSection levelChunkSection = levelChunkSections[i];
; ++i)
{
LevelChunkSection levelChunkSection = levelChunkSections[i];
#if PRE_MC_1_17_1
if (!LevelChunkSection.isEmpty(levelChunkSection)) {
updateSectionStatus(SectionPos.of(chunkPos, i), false);
}
#elif PRE_MC_1_18_2
if (!LevelChunkSection.isEmpty(levelChunkSection)) {
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
updateSectionStatus(SectionPos.of(chunkPos, j), false);
}
if (!LevelChunkSection.isEmpty(levelChunkSection))
{
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
updateSectionStatus(SectionPos.of(chunkPos, j), false);
}
#else
if (levelChunkSection.hasOnlyAir()) continue;
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
if (levelChunkSection.hasOnlyAir()) continue;
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
#if POST_MC_1_20_1
queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, i), null);
queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, i), null);
queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, i), null);
queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, i), null);
#endif
updateSectionStatus(SectionPos.of(chunkPos, j), false);
updateSectionStatus(SectionPos.of(chunkPos, j), false);
#endif
}
}
#if PRE_MC_1_20_1
enableLightSources(chunkPos, true);
if (needLightBlockUpdate) {
chunkAccess.getLights().forEach(blockPos ->
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
enableLightSources(chunkPos, true);
if (needLightBlockUpdate)
{
chunkAccess.getLights().forEach(blockPos ->
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
#else
//runLightUpdates();
propagateLightSources(chunkPos);
//runLightUpdates();
//runLightUpdates();
propagateLightSources(chunkPos);
//runLightUpdates();
#endif
chunkAccess.setLightCorrect(true);
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.retainData(chunkPos, bl);
}
}
#if POST_MC_1_17_1
@Override
public int getLightSectionCount() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMinLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMaxLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
chunkAccess.setLightCorrect(true);
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos)
{
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl)
{
if (this.blockEngine != null)
{
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null)
{
this.skyEngine.retainData(chunkPos, bl);
}
}
#if POST_MC_1_17_1
@Override
public int getLightSectionCount()
{
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMinLightSection()
{
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMaxLightSection()
{
throw new UnsupportedOperationException("This should never be used!");
}
#endif
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
import java.util.Iterator;
@@ -59,40 +59,45 @@ import net.minecraft.world.level.levelgen.feature.StructureFeature;
public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatureManager #else StructureManager #endif
public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatureManager #else StructureManager #endif
{
final WorldGenLevel genLevel;
#if PRE_MC_1_19_4
WorldGenSettings worldGenSettings;
#else
WorldOptions worldOptions;
#endif
#if POST_MC_1_18_2
StructureCheck structureCheck;
#endif
#if PRE_MC_1_19_4
public WorldGenStructFeatManager(WorldGenSettings worldGenSettings,
WorldGenLevel genLevel #if POST_MC_1_18_2 , StructureCheck structureCheck #endif ) {
public WorldGenStructFeatManager(
WorldGenSettings worldGenSettings,
WorldGenLevel genLevel #if POST_MC_1_18_2 , StructureCheck structureCheck #endif )
{
super(genLevel, worldGenSettings #if POST_MC_1_18_2 , structureCheck #endif );
this.genLevel = genLevel;
this.worldGenSettings = worldGenSettings;
}
#else
public WorldGenStructFeatManager(WorldOptions worldOptions,
WorldGenLevel genLevel, StructureCheck structureCheck) {
public WorldGenStructFeatManager(
WorldOptions worldOptions,
WorldGenLevel genLevel, StructureCheck structureCheck)
{
super(genLevel, worldOptions, structureCheck);
this.genLevel = genLevel;
this.worldOptions = worldOptions;
}
#endif
@Override
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion)
{
if (worldGenRegion == genLevel)
return this;
#if PRE_MC_1_19_4
@@ -101,19 +106,22 @@ public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatur
return new WorldGenStructFeatManager(worldOptions, worldGenRegion, structureCheck);
#endif
}
private ChunkAccess _getChunk(int x, int z, ChunkStatus status) {
private ChunkAccess _getChunk(int x, int z, ChunkStatus status)
{
if (genLevel == null) return null;
return genLevel.getChunk(x, z, status, false);
}
#if PRE_MC_1_18_2
@Override
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos2,
StructureFeature<?> structureFeature) {
public Stream<? extends StructureStart<?>> startsForFeature(
SectionPos sectionPos2,
StructureFeature<?> structureFeature)
{
ChunkAccess chunk = _getChunk(sectionPos2.x(), sectionPos2.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return Stream.empty();
return chunk.getReferencesForFeature(structureFeature).stream().map(pos -> {
SectionPos sectPos = SectionPos.of(ChunkPos.getX(pos), 0, ChunkPos.getZ(pos));
ChunkAccess startChunk = _getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS);
@@ -123,13 +131,14 @@ public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatur
}
#else
@Override
public boolean hasAnyStructureAt(BlockPos blockPos) {
public boolean hasAnyStructureAt(BlockPos blockPos)
{
SectionPos sectionPos = SectionPos.of(blockPos);
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return false;
return chunk.hasAnyStructureReferences();
}
#if MC_1_18_1
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -157,34 +166,38 @@ public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatur
#else
#if PRE_MC_1_19_2
@Override
public List<StructureStart> startsForFeature(SectionPos sectionPos, Predicate<ConfiguredStructureFeature<?, ?>> predicate) {
public List<StructureStart> startsForFeature(SectionPos sectionPos, Predicate<ConfiguredStructureFeature<?, ?>> predicate)
{
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return List.of();
// Copied from StructureFeatureManager::startsForFeature(...)
Map<ConfiguredStructureFeature<?, ?>, LongSet> map = chunk.getAllReferences();
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
Iterator<Map.Entry<ConfiguredStructureFeature<?, ?>, LongSet>> var5 = map.entrySet().iterator();
while(var5.hasNext()) {
while (var5.hasNext())
{
Map.Entry<ConfiguredStructureFeature<?, ?>, LongSet> entry = var5.next();
ConfiguredStructureFeature<?, ?> configuredStructureFeature = entry.getKey();
if (predicate.test(configuredStructureFeature)) {
LongSet var10002 = (LongSet)entry.getValue();
if (predicate.test(configuredStructureFeature))
{
LongSet var10002 = (LongSet) entry.getValue();
Objects.requireNonNull(builder);
this.fillStartsForFeature(configuredStructureFeature, var10002, builder::add);
}
}
return builder.build();
}
@Override
public List<StructureStart> startsForFeature(SectionPos sectionPos, ConfiguredStructureFeature<?, ?> configuredStructureFeature) {
public List<StructureStart> startsForFeature(SectionPos sectionPos, ConfiguredStructureFeature<?, ?> configuredStructureFeature)
{
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return (List<StructureStart>) Stream.empty();
// Copied from StructureFeatureManager::startsForFeature(...)
LongSet longSet = chunk.getReferencesForFeature(configuredStructureFeature);
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
@@ -192,44 +205,49 @@ public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatur
this.fillStartsForFeature(configuredStructureFeature, longSet, builder::add);
return builder.build();
}
@Override
public Map<ConfiguredStructureFeature<?, ?>, LongSet> getAllStructuresAt(BlockPos blockPos) {
public Map<ConfiguredStructureFeature<?, ?>, LongSet> getAllStructuresAt(BlockPos blockPos)
{
SectionPos sectionPos = SectionPos.of(blockPos);
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return (Map<ConfiguredStructureFeature<?, ?>, LongSet>) Stream.empty();
return chunk.getAllReferences();
return chunk.getAllReferences();
}
#else
@Override
public List<StructureStart> startsForStructure(ChunkPos sectionPos, Predicate<Structure> predicate) {
public List<StructureStart> startsForStructure(ChunkPos sectionPos, Predicate<Structure> predicate)
{
ChunkAccess chunk = _getChunk(sectionPos.x, sectionPos.z, ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return List.of();
// Copied from StructureFeatureManager::startsForFeature(...)
Map<Structure, LongSet> map = chunk.getAllReferences();
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
Iterator<Map.Entry<Structure, LongSet>> var5 = map.entrySet().iterator();
while (var5.hasNext()) {
while (var5.hasNext())
{
Map.Entry<Structure, LongSet> entry = var5.next();
Structure configuredStructureFeature = entry.getKey();
if (predicate.test(configuredStructureFeature)) {
if (predicate.test(configuredStructureFeature))
{
LongSet var10002 = (LongSet) entry.getValue();
Objects.requireNonNull(builder);
this.fillStartsForStructure(configuredStructureFeature, var10002, builder::add);
}
}
return builder.build();
}
@Override
public List<StructureStart> startsForStructure(SectionPos sectionPos, Structure structure) {
public List<StructureStart> startsForStructure(SectionPos sectionPos, Structure structure)
{
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return (List<StructureStart>) Stream.empty();
// Copied from StructureFeatureManager::startsForFeature(...)
LongSet longSet = chunk.getReferencesForStructure(structure);
ImmutableList.Builder<StructureStart> builder = ImmutableList.builder();
@@ -237,9 +255,10 @@ public class WorldGenStructFeatManager extends #if PRE_MC_1_19_2 StructureFeatur
this.fillStartsForStructure(structure, longSet, builder::add);
return builder.build();
}
@Override
public Map<Structure, LongSet> getAllStructuresAt(BlockPos blockPos) {
public Map<Structure, LongSet> getAllStructuresAt(BlockPos blockPos)
{
SectionPos sectionPos = SectionPos.of(blockPos);
ChunkAccess chunk = _getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES);
if (chunk == null) return (Map<Structure, LongSet>) Stream.empty();
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
@@ -36,12 +36,13 @@ import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.blending.Blender;
#endif
public final class StepBiomes {
public final class StepBiomes
{
/**
*
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -49,12 +50,14 @@ public final class StepBiomes {
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.BIOMES;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers) {
public void generateGroup(
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers)
{
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkWrapper chunkWrapper : chunkWrappers)
@@ -65,7 +68,8 @@ public final class StepBiomes {
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
for (ChunkAccess chunk : chunksToDo)
{
// System.out.println("StepBiomes: "+chunk.getPos());
#if PRE_MC_1_18_2
environment.params.generator.createBiomes(environment.params.biomes, chunk);
@@ -81,4 +85,5 @@ public final class StepBiomes {
#endif
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
@@ -35,12 +35,13 @@ import net.minecraft.world.level.levelgen.Heightmap;
#if POST_MC_1_18_2
#endif
public final class StepFeatures {
public final class StepFeatures
{
/**
*
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -48,11 +49,13 @@ public final class StepFeatures {
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.FEATURES;
public void generateGroup(ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
ArrayGridList<ChunkWrapper> chunkWrappers) {
public void generateGroup(
ThreadedParameters tParams, DhLitWorldGenRegion worldGenRegion,
ArrayGridList<ChunkWrapper> chunkWrappers)
{
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkWrapper chunkWrapper : chunkWrappers)
@@ -63,8 +66,10 @@ public final class StepFeatures {
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
try {
for (ChunkAccess chunk : chunksToDo)
{
try
{
#if PRE_MC_1_18_2
worldGenRegion.setOverrideCenter(chunk.getPos());
environment.params.generator.applyBiomeDecoration(worldGenRegion, tParams.structFeat);
@@ -76,11 +81,14 @@ public final class StepFeatures {
Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter());
BatchGenerationEnvironment.clearDistantGenerationMixinData();
#endif
} catch (ReportedException e) {
}
catch (ReportedException e)
{
e.printStackTrace();
// FIXME: Features concurrent modification issue. Something about cocobeans might just
// error out. For now just retry.
}
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -35,12 +35,13 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.lighting.LightEventListener;
#endif
public final class StepLight {
public final class StepLight
{
/**
*
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -48,13 +49,14 @@ public final class StepLight {
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
public void generateGroup(
#if PRE_MC_1_17_1 LevelLightEngine lightEngine,
#else LightEventListener lightEngine, #endif
ArrayGridList<ChunkWrapper> chunkWrappers) {
ArrayGridList<ChunkWrapper> chunkWrappers)
{
for (ChunkWrapper chunkWrapper : chunkWrappers)
{
@@ -67,27 +69,37 @@ public final class StepLight {
{
ChunkAccess chunk = chunkWrapper.getChunk();
boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
try {
if (lightEngine == null) {
try
{
if (lightEngine == null)
{
// Do nothing
} else if (lightEngine instanceof WorldGenLevelLightEngine) {
((WorldGenLevelLightEngine)lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
} else if (lightEngine instanceof ThreadedLevelLightEngine) {
}
else if (lightEngine instanceof WorldGenLevelLightEngine)
{
((WorldGenLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
}
else if (lightEngine instanceof ThreadedLevelLightEngine)
{
((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
} else {
assert(false);
}
else
{
assert (false);
}
} catch (Exception e) {
}
catch (Exception e)
{
e.printStackTrace();
}
#if POST_MC_1_18_2 && PRE_MC_1_20_1
if (chunk instanceof LevelChunk) ((LevelChunk)chunk).setClientLightReady(true);
if (chunk instanceof LevelChunk) ((LevelChunk) chunk).setClientLightReady(true);
#elif POST_MC_1_20_1
lightEngine.setLightEnabled(chunk.getPos(), true);
#endif
chunk.setLightCorrect(true);
}
#if PRE_MC_1_20_1
@@ -96,4 +108,5 @@ public final class StepLight {
lightEngine.runLightUpdates();
#endif
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
@@ -39,12 +39,13 @@ import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.blending.Blender;
#endif
public final class StepNoise {
public final class StepNoise
{
/**
*
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -54,10 +55,12 @@ public final class StepNoise {
}
public final ChunkStatus STATUS = ChunkStatus.NOISE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers) {
public void generateGroup(
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers)
{
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkWrapper chunkWrapper : chunkWrappers)
@@ -68,7 +71,8 @@ public final class StepNoise {
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
for (ChunkAccess chunk : chunksToDo)
{
// System.out.println("StepNoise: "+chunk.getPos());
#if PRE_MC_1_17_1
environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
@@ -85,4 +89,5 @@ public final class StepNoise {
UncheckedInterruptedException.throwIfInterrupted();
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
@@ -33,12 +33,13 @@ import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
public final class StepStructureReference {
public final class StepStructureReference
{
/**
*
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -46,12 +47,14 @@ public final class StepStructureReference {
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers) {
public void generateGroup(
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers)
{
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkWrapper chunkWrapper : chunkWrappers)
@@ -62,9 +65,11 @@ public final class StepStructureReference {
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
for (ChunkAccess chunk : chunksToDo)
{
// System.out.println("StepStructureReference: "+chunk.getPos());
environment.params.generator.createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
@@ -38,7 +38,7 @@ public final class StepStructureStart
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -46,20 +46,24 @@ public final class StepStructureStart
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
public static class StructStartCorruptedException extends RuntimeException {
public static class StructStartCorruptedException extends RuntimeException
{
private static final long serialVersionUID = -8987434342051563358L;
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e)
{
super("StructStartCorruptedException");
super.initCause(e);
fillInStackTrace();
}
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
public void generateGroup(
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers)
{
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
@@ -75,11 +79,13 @@ public final class StepStructureStart
}
#if PRE_MC_1_19_2
if (environment.params.worldGenSettings.generateFeatures()) {
if (environment.params.worldGenSettings.generateFeatures())
{
#elif PRE_MC_1_19_4
if (environment.params.worldGenSettings.generateStructures()) {
#else
if (environment.params.worldOptions.generateStructures()) {
if (environment.params.worldOptions.generateStructures())
{
#endif
for (ChunkAccess chunk : chunksToDo)
{
@@ -117,7 +123,7 @@ public final class StepStructureStart
catch (ArrayIndexOutOfBoundsException secondEx)
{
// the structure logic failed again, log it and move on
LOGGER.error("Unable to create structure starts for "+chunk.getPos()+". This is an error with MC's world generation. Ignoring and continuing generation. Error: "+secondEx.getMessage()); // don't log the full stack trace since it is long and will generally end up in MC's code
LOGGER.error("Unable to create structure starts for " + chunk.getPos() + ". This is an error with MC's world generation. Ignoring and continuing generation. Error: " + secondEx.getMessage()); // don't log the full stack trace since it is long and will generally end up in MC's code
//throw new StepStructureStart.StructStartCorruptedException(secondEx);
}
@@ -126,4 +132,5 @@ public final class StepStructureStart
}
}
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
@@ -31,12 +31,13 @@ import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
public final class StepSurface {
public final class StepSurface
{
/**
*
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
@@ -44,11 +45,13 @@ public final class StepSurface {
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.SURFACE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers) {
public void generateGroup(
ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkWrapper> chunkWrappers)
{
ArrayList<ChunkAccess> chunksToDo = new ArrayList<>();
for (ChunkWrapper chunkWrapper : chunkWrappers)
@@ -59,7 +62,8 @@ public final class StepSurface {
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
for (ChunkAccess chunk : chunksToDo)
{
// System.out.println("StepSurface: "+chunk.getPos());
#if PRE_MC_1_18_2
environment.params.generator.buildSurfaceAndBedrock(worldGenRegion, chunk);
@@ -70,4 +74,5 @@ public final class StepSurface {
#endif
}
}
}
@@ -67,7 +67,7 @@ import org.lwjgl.opengl.GL15;
/**
* This handles all events sent to the client,
* and is the starting point for most of the mod.
*
*
* @author coolGi
* @author Ran
* @version 2023-7-27
@@ -80,7 +80,7 @@ public class FabricClientProxy
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
// TODO we shouldn't be filtering keys on the Forge/Fabric side, only in ClientApi
private static final int[] KEY_TO_CHECK_FOR = { GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8, GLFW.GLFW_KEY_P};
private static final int[] KEY_TO_CHECK_FOR = {GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8, GLFW.GLFW_KEY_P};
HashSet<Integer> previouslyPressKeyCodes = new HashSet<>();
@@ -88,6 +88,7 @@ public class FabricClientProxy
/**
* Registers Fabric Events
*
* @author Ran
*/
public void registerEvents()
@@ -148,7 +149,7 @@ public class FabricClientProxy
});
// (kinda) block place event
UseBlockCallback.EVENT.register((player, level, hand, hitResult) ->
UseBlockCallback.EVENT.register((player, level, hand, hitResult) ->
{
// if we have access to the server, use the chunk save event instead
if (MC.clientConnectedToDedicatedServer())
@@ -221,16 +222,16 @@ public class FabricClientProxy
#endif
}
}
if (immersivePortalsAccessor != null)
{
immersivePortalsAccessor.partialTicks = renderContext.tickDelta();
}
});
// Debug keyboard event
// FIXME: Use better hooks so it doesn't trigger key press events in text boxes
ClientTickEvents.END_CLIENT_TICK.register(client ->
ClientTickEvents.END_CLIENT_TICK.register(client ->
{
if (client.player != null && !(Minecraft.getInstance().screen instanceof TitleScreen))
{
@@ -243,7 +244,7 @@ public class FabricClientProxy
//==================//
// networking event //
//==================//
// ClientPlayNetworking.registerGlobalReceiver(new ResourceLocation(ModInfo.NETWORKING_RESOURCE_NAMESPACE, ModInfo.MULTIVERSE_PLUGIN_NAMESPACE),
// (Minecraft client, ClientPacketListener handler, FriendlyByteBuf friendlyByteBuf, PacketSender responseSender) ->
// {
@@ -35,7 +35,7 @@ public class FabricDedicatedServerMain implements DedicatedServerModInitializer
server_proxy = new FabricServerProxy(true);
server_proxy.registerEvents();
ServerLifecycleEvents.SERVER_STARTING.register((server) ->
ServerLifecycleEvents.SERVER_STARTING.register((server) ->
{
if (this.hasPostSetupDone)
{
@@ -49,7 +49,8 @@ public class FabricDedicatedServerMain implements DedicatedServerModInitializer
LodCommonMain.initConfig();
FabricMain.postInit();
LOGGER.info("Dedicated server initialized at "+server.getServerDirectory());
LOGGER.info("Dedicated server initialized at " + server.getServerDirectory());
});
}
}
@@ -40,7 +40,7 @@ import org.apache.logging.log4j.Logger;
* Initialize and setup the Mod. <br>
* If you are looking for the real start of the mod
* check out the ClientProxy.
*
*
* @author coolGi
* @author Ran
* @version 9-2-2022
@@ -48,25 +48,26 @@ import org.apache.logging.log4j.Logger;
public class FabricMain
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static void postInit() {
public static void postInit()
{
LOGGER.info("Post-Initializing Mod");
FabricDependencySetup.runDelayedSetup();
if (Config.Client.Advanced.Graphics.Fog.disableVanillaFog.get() && SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib"))
ModAccessorInjector.INSTANCE.get(IBCLibAccessor.class).setRenderCustomFog(false); // Remove BCLib's fog
#if POST_MC_1_20_1
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("sodium"))
ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class).setFogOcclusion(false); // FIXME: This is a temporary solution to get sodium 0.5 to work
#endif
if (ConfigBase.INSTANCE == null)
throw new IllegalStateException("Config was not initialized. Make sure to call LodCommonMain.initConfig() before calling this method.");
LOGGER.info("Mod Post-Initialized");
}
// This loads the mod after minecraft loads which doesn't causes a lot of issues
public static void init()
{
@@ -76,29 +77,35 @@ public class FabricMain
LodCommonMain.startup(null);
FabricDependencySetup.createInitialBindings();
LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
// Print git info (Useful for dev builds)
LOGGER.info("DH Branch: "+ ModGitInfo.Git_Main_Branch);
LOGGER.info("DH Commit: "+ ModGitInfo.Git_Main_Commit);
LOGGER.info("DH-Core Commit: "+ ModGitInfo.Git_Core_Commit);
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("sodium")) {
LOGGER.info("DH Branch: " + ModGitInfo.Git_Main_Branch);
LOGGER.info("DH Commit: " + ModGitInfo.Git_Main_Commit);
LOGGER.info("DH-Core Commit: " + ModGitInfo.Git_Core_Commit);
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("sodium"))
{
ModAccessorInjector.INSTANCE.bind(ISodiumAccessor.class, new SodiumAccessor());
}
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("imm_ptl_core")) {
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("imm_ptl_core"))
{
ModAccessorInjector.INSTANCE.bind(IImmersivePortalsAccessor.class, new ImmersivePortalsAccessor());
}
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("starlight")) {
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("starlight"))
{
ModAccessorInjector.INSTANCE.bind(IStarlightAccessor.class, new StarlightAccessor());
}
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("optifine")) {
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("optifine"))
{
ModAccessorInjector.INSTANCE.bind(IOptifineAccessor.class, new OptifineAccessor());
}
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib")) {
if (SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib"))
{
ModAccessorInjector.INSTANCE.bind(IBCLibAccessor.class, new BCLibAccessor());
}
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
}
}
@@ -36,45 +36,45 @@ public class FabricServerProxy
{
private static final ServerApi SERVER_API = ServerApi.INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicated;
public static Supplier<Boolean> isGenerationThreadChecker = null;
public FabricServerProxy(boolean isDedicated)
{
this.isDedicated = isDedicated;
}
private boolean isValidTime()
{
if (isDedicated)
{
return true;
}
//FIXME: This may cause init issue...
return !(Minecraft.getInstance().screen instanceof TitleScreen);
}
private IClientLevelWrapper getClientLevelWrapper(ClientLevel level) { return ClientLevelWrapper.getWrapper(level); }
private ServerLevelWrapper getServerLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
private ServerPlayerWrapper getServerPlayerWrapper(ServerPlayer player) { return ServerPlayerWrapper.getWrapper(player); }
/** Registers Fabric Events */
public void registerEvents()
{
LOGGER.info("Registering Fabric Server Events");
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
/* Register the mod needed event callbacks */
// ServerTickEvent
ServerTickEvents.END_SERVER_TICK.register((server) -> SERVER_API.serverTickEvent());
// ServerWorldLoadEvent
//TODO: Check if both of these use the correct timed events. (i.e. is it 'ed' or 'ing' one?)
ServerLifecycleEvents.SERVER_STARTING.register((server) ->
@@ -92,7 +92,7 @@ public class FabricServerProxy
ServerApi.INSTANCE.serverUnloadEvent();
}
});
// ServerLevelLoadEvent
ServerWorldEvents.LOAD.register((server, level) ->
{
@@ -109,7 +109,7 @@ public class FabricServerProxy
ServerApi.INSTANCE.serverLevelUnloadEvent(getServerLevelWrapper(level));
}
});
// ServerChunkLoadEvent
ServerChunkEvents.CHUNK_LOAD.register((server, chunk) ->
{
@@ -122,7 +122,7 @@ public class FabricServerProxy
}
});
// ServerChunkSaveEvent - Done in MixinChunkMap
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) ->
{
if (isValidTime())
@@ -138,5 +138,5 @@ public class FabricServerProxy
}
});
}
}
@@ -13,50 +13,60 @@ import java.util.Set;
* @author cortex
*/
// TODO: Move to common if possible
public class FabricMixinPlugin implements IMixinConfigPlugin {
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (mixinClassName.contains(".mods.")) { // If the mixin wants to go into a mod then we check if that mod is loaded or not
return FabricLoader.getInstance().isModLoaded(
mixinClassName
// What these 2 regex's do is get the mod name that we are checking out of the mixinClassName
// Eg. "com.seibel.distanthorizons.mixins.mods.sodium.MixinSodiumChunkRenderer" turns into "sodium"
.replaceAll("^.*mods.", "") // Replaces everything before the mods
.replaceAll("\\..*$", "") // Replaces everything after the mod name
);
}
return true;
}
@Override
public void onLoad(String mixinPackage) {
}
@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 targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
public class FabricMixinPlugin implements IMixinConfigPlugin
{
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
{
if (mixinClassName.contains(".mods."))
{ // If the mixin wants to go into a mod then we check if that mod is loaded or not
return FabricLoader.getInstance().isModLoaded(
mixinClassName
// What these 2 regex's do is get the mod name that we are checking out of the mixinClassName
// Eg. "com.seibel.distanthorizons.mixins.mods.sodium.MixinSodiumChunkRenderer" turns into "sodium"
.replaceAll("^.*mods.", "") // Replaces everything before the mods
.replaceAll("\\..*$", "") // Replaces everything after the mod name
);
}
return true;
}
@Override
public void onLoad(String mixinPackage)
{
}
@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 targetClass, String mixinClassName, IMixinInfo mixinInfo)
{
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo)
{
}
}
@@ -16,7 +16,7 @@
* 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.fabric.mixins.client;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -33,8 +33,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* This class is used for world loading events
* @author Ran
*
* @author Ran
*/
@Mixin(ClientLevel.class)
@@ -48,10 +48,10 @@ public class MixinClientLevel
// {
// ClientApi.INSTANCE.clientLevelLoadEvent(WorldWrapper.getWorldWrapper((ClientLevel)(Object)this));
// }
// Moved to overriding the enableChunkLight(...) method over at ClientPacketListener for 1.20+
// Moved to overriding the enableChunkLight(...) method over at ClientPacketListener for 1.20+
#if POST_MC_1_18_2 && PRE_MC_1_20_1 // Only the setLightReady is only available after 1.18. This ensures the light data is ready.
@Inject(method = "setLightReady", at = @At("HEAD"))
@Inject(method = "setLightReady", at = @At("HEAD"))
private void onChunkLightReady(int x, int z, CallbackInfo ci)
{
ClientLevel clientLevel = (ClientLevel) (Object) this;
@@ -19,12 +19,12 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@Mixin(ClientPacketListener.class)
public class MixinClientPacketListener
{
@Shadow
private ClientLevel level;
@Shadow
private ClientLevel level;
@Inject(method = "handleLogin", at = @At("HEAD"))
@Inject(method = "handleLogin", at = @At("HEAD"))
void onHandleLoginStart(CallbackInfo ci)
{
// not the best way to notify Core that we are no longer in the previous world, but it will have to do for now
@@ -37,7 +37,7 @@ public class MixinClientPacketListener
void onHandleRespawnStart(CallbackInfo ci) { ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(level)); }
@Inject(method = "handleRespawn", at = @At("RETURN"))
void onHandleRespawnEnd(CallbackInfo ci) { ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level)); }
#if PRE_MC_1_19_4
@Inject(method = "cleanup", at = @At("HEAD"))
#else
@@ -51,7 +51,7 @@ public class MixinClientPacketListener
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(level));
}
}
#if POST_MC_1_20_1
@Inject(method = "enableChunkLight", at = @At("TAIL"))
void onEnableChunkLight(LevelChunk chunk, int x, int z, CallbackInfo ci)
@@ -61,5 +61,5 @@ public class MixinClientPacketListener
}
#endif
}
@@ -10,12 +10,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(DebugScreenOverlay.class)
public class MixinDebugScreenOverlay {
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void addCustomF3(CallbackInfoReturnable<List<String>> cir) {
List<String> messages = cir.getReturnValue();
F3Screen.addStringToDisplay(messages);
}
public class MixinDebugScreenOverlay
{
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void addCustomF3(CallbackInfoReturnable<List<String>> cir)
{
List<String> messages = cir.getReturnValue();
F3Screen.addStringToDisplay(messages);
}
}
@@ -16,7 +16,7 @@
* 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.fabric.mixins.client;
import com.seibel.distanthorizons.core.config.Config;
@@ -40,17 +40,20 @@ import net.minecraft.world.level.material.FogType;
#endif
@Mixin(FogRenderer.class)
public class MixinFogRenderer {
public class MixinFogRenderer
{
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"), method = "setupFog")
#if PRE_MC_1_19_2
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback)
{
#else
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback) {
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
{
#endif
#if PRE_MC_1_17_1
FluidState fluidState = camera.getFluidInCamera();
@@ -59,7 +62,7 @@ public class MixinFogRenderer {
FogType fogTypes = camera.getFluidInCamera();
boolean cameraNotInFluid = fogTypes == FogType.NONE;
#endif
Entity entity = camera.getEntity();
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
@@ -74,4 +77,5 @@ public class MixinFogRenderer {
#endif
}
}
}
@@ -17,26 +17,30 @@ public class MixinGameRenderer
#if POST_MC_1_17_1
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci) {
LOGGER.info("Starting up renderer (fabric)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci)
{
LOGGER.info("Starting up renderer (fabric)");
if (!DependencySetupDoneCheck.isDone)
{
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
@Inject(method = "shutdownShaders", at = @At("HEAD"))
public void onShutdownShaders(CallbackInfo ci) {
LOGGER.info("Shutting down renderer (fabric)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
public void onShutdownShaders(CallbackInfo ci)
{
LOGGER.info("Shutting down renderer (fabric)");
if (!DependencySetupDoneCheck.isDone)
{
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
#else
// FIXME: on 1.16 we dont have stuff for reloading/shutting down shaders
@@ -55,13 +55,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LevelRenderer.class)
public class MixinLevelRenderer
{
@Shadow
private ClientLevel level;
@Unique
private static float previousPartialTicks = 0;
// Inject rendering at first call to renderChunkLayer
// HEAD or RETURN
@Shadow
private ClientLevel level;
@Unique
private static float previousPartialTicks = 0;
// Inject rendering at first call to renderChunkLayer
// HEAD or RETURN
#if PRE_MC_1_17_1
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
@@ -71,67 +71,68 @@ public class MixinLevelRenderer
previousPartialTicks = partialTicks;
}
#else
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = tickDelta;
}
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci)
{
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = tickDelta;
}
#endif
#if PRE_MC_1_17_1
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDD)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
#elif PRE_MC_1_19_4
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
#else
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
#endif
{
{
// FIXME completely disables rendering when sodium is installed
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
{
callback.cancel();
callback.cancel();
}
}
@Redirect(method =
"Lnet/minecraft/client/renderer/LevelRenderer;" +
"renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;" +
"FJZLnet/minecraft/client/Camera;" +
"Lnet/minecraft/client/renderer/GameRenderer;" +
"Lnet/minecraft/client/renderer/LightTexture;" +
}
@Redirect(method =
"Lnet/minecraft/client/renderer/LevelRenderer;" +
"renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;" +
"FJZLnet/minecraft/client/Camera;" +
"Lnet/minecraft/client/renderer/GameRenderer;" +
"Lnet/minecraft/client/renderer/LightTexture;" +
#if PRE_MC_1_19_4
"Lcom/mojang/math/Matrix4f;)V"
#else
"Lorg/joml/Matrix4f;)V"
#endif
,
at = @At(
value = "INVOKE",
#if PRE_MC_1_20_1
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"
#else
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"
#endif
))
private int callAfterRunUpdates(LevelLightEngine light #if PRE_MC_1_20_1 , int pos, boolean isQueueEmpty, boolean updateBlockLight #endif)
{
"Lcom/mojang/math/Matrix4f;)V"
#else
"Lorg/joml/Matrix4f;)V"
#endif
,
at = @At(
value = "INVOKE",
#if PRE_MC_1_20_1
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"
#else
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"
#endif
))
private int callAfterRunUpdates(LevelLightEngine light #if PRE_MC_1_20_1 , int pos, boolean isQueueEmpty, boolean updateBlockLight #endif )
{
#if PRE_MC_1_20_1
int r = light.runUpdates(pos, isQueueEmpty, updateBlockLight);
int r = light.runUpdates(pos, isQueueEmpty, updateBlockLight);
#else
int r = light.runLightUpdates();
int r = light.runLightUpdates();
#endif
ChunkWrapper.syncedUpdateClientLightStatus();
return r;
}
ChunkWrapper.syncedUpdateClientLightStatus();
return r;
}
}
@@ -12,16 +12,19 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LightTexture.class)
public class MixinLightmap {
@Shadow
@Final
public NativeImage lightPixels;
@Inject(method="updateLightTexture", at=@At(
value="INVOKE",
target="Lnet/minecraft/client/renderer/texture/DynamicTexture;upload()V"))
public void updateLightTexture(float f, CallbackInfo ci) {
//ApiShared.LOGGER.info("Lightmap update");
MinecraftRenderWrapper.INSTANCE.updateLightmap(lightPixels);
}
public class MixinLightmap
{
@Shadow
@Final
public NativeImage lightPixels;
@Inject(method = "updateLightTexture", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;upload()V"))
public void updateLightTexture(float f, CallbackInfo ci)
{
//ApiShared.LOGGER.info("Lightmap update");
MinecraftRenderWrapper.INSTANCE.updateLightmap(lightPixels);
}
}
@@ -23,32 +23,33 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Minecraft.class)
public class MixinMinecraft
{
@Redirect(
method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
)
public void onOpenScreen(Minecraft instance, Screen guiScreen)
@Redirect(
method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
)
public void onOpenScreen(Minecraft instance, Screen guiScreen)
{
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
{
// Don't do anything if the user doesn't want it
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
return;
}
if (SelfUpdater.onStart())
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion())
));
}
// Don't do anything if the user doesn't want it
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
return;
}
if (SelfUpdater.onStart())
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion())
));
}
else
{
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
}
}
@Inject(at = @At("HEAD"), method = "close()V")
public void close(CallbackInfo ci) { SelfUpdater.onClose(); }
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
}
}
@Inject(at = @At("HEAD"), method = "close()V")
public void close(CallbackInfo ci) { SelfUpdater.onClose(); }
}
@@ -42,36 +42,40 @@ import java.util.Objects;
*
* @author coolGi
* @version 12-02-2021
*/
*/
@Mixin(OptionsScreen.class)
public class MixinOptionsScreen extends Screen {
// Get the texture for the button
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID,"textures/gui/button.png");
protected MixinOptionsScreen(Component title) {
super(title);
}
@Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) {
if (Config.Client.optionsButton.get())
this. #if PRE_MC_1_17_1 addButton #else addRenderableWidget #endif
(new TexturedButtonWidget(
// 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
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
// Add a title to the utton
public class MixinOptionsScreen extends Screen
{
// Get the texture for the button
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
protected MixinOptionsScreen(Component title)
{
super(title);
}
@Inject(at = @At("HEAD"), method = "init")
private void lodconfig$init(CallbackInfo ci)
{
if (Config.Client.optionsButton.get())
this. #if PRE_MC_1_17_1 addButton #else addRenderableWidget #endif
(new TexturedButtonWidget(
// 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
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
// Add a title to the utton
#if PRE_MC_1_19_2
new TranslatableComponent(ModInfo.ID + ".title")));
new TranslatableComponent(ModInfo.ID + ".title")));
#else
Component.translatable(ModInfo.ID + ".title")));
Component.translatable(ModInfo.ID + ".title")));
#endif
}
}
}
@@ -13,15 +13,19 @@ import org.spongepowered.asm.mixin.injection.Redirect;
* @author coolGi
*/
@Mixin(TextureUtil.class)
public class MixinTextureUtil {
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", remap=false))
private static void setLodBias(int target, int pname, float param) {
float biasValue = Config.Client.Advanced.Graphics.AdvancedGraphics.lodBias.get().floatValue();
if (biasValue != 0) {
// The target is GL11.GL_TEXTURE_2D
// And the pname is GL14.GL_TEXTURE_LOD_BIAS
GlStateManager._texParameter(target, pname, biasValue);
}
}
public class MixinTextureUtil
{
@Redirect(method = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", remap = false))
private static void setLodBias(int target, int pname, float param)
{
float biasValue = Config.Client.Advanced.Graphics.AdvancedGraphics.lodBias.get().floatValue();
if (biasValue != 0)
{
// The target is GL11.GL_TEXTURE_2D
// And the pname is GL14.GL_TEXTURE_LOD_BIAS
GlStateManager._texParameter(target, pname, biasValue);
}
}
}
@@ -16,7 +16,7 @@
* 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.fabric.mixins.events;
import net.minecraft.core.BlockPos;
@@ -31,10 +31,11 @@ import org.spongepowered.asm.mixin.Shadow;
*/
@Mixin(ClientboundBlockUpdatePacket.class)
@Deprecated
public abstract class MixinBlockUpdate {
@Shadow public abstract BlockPos getPos();
//TODO: Check if this event will be needed in new reworked system
public abstract class MixinBlockUpdate
{
@Shadow public abstract BlockPos getPos();
//TODO: Check if this event will be needed in new reworked system
// @Inject(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At("TAIL"))
// private void onBlockUpdate(ClientGamePacketListener clientGamePacketListener, CallbackInfo ci) {
// Main.client_proxy.blockChangeEvent(Minecraft.getInstance().player.clientLevel, this.getPos());
@@ -16,7 +16,7 @@
* 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.fabric.mixins.events;
import net.minecraft.server.level.ServerLevel;
@@ -24,11 +24,13 @@ import org.spongepowered.asm.mixin.Mixin;
/**
* This class is used for world saving events
*
* @author Ran
*/
@Mixin(ServerLevel.class)
@Deprecated // TODO: Not sure if this is needed anymore
public class MixinServerLevel {
public class MixinServerLevel
{
// #if PRE_MC_1_17_1
// @Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;save(Z)V", shift = At.Shift.AFTER))
// private void saveWorldEvent(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
@@ -2,6 +2,7 @@ package com.seibel.distanthorizons.fabric.mixins.mods.sodium;
#if POST_MC_1_20_1
// Sodium 0.5
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
@@ -23,33 +24,34 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RegionChunkRenderer.class)
public class MixinSodiumRenderer
{
@Unique SodiumAccessor accessor = null;
@Inject(remap = false, method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/ShaderChunkRenderer;begin(Lme/jellysquid/mods/sodium/client/render/chunk/terrain/TerrainRenderPass;)V", shift = At.Shift.AFTER))
private void injectDHLoDRendering(ChunkRenderMatrices matrices, CommandList commandList, RenderRegionManager regions, SortedRenderLists renderLists, TerrainRenderPass renderPass, ChunkCameraContext camera, CallbackInfo ci)
{
if (accessor == null)
{
accessor = (SodiumAccessor)ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
}
if (renderPass.equals(DefaultTerrainRenderPasses.SOLID))
{
//TODO: use matrices.modelView() and matrices.projection() instead of
// SodiumAccessor.mcModelViewMatrix,
// SodiumAccessor.mcProjectionMatrix,
ClientApi.INSTANCE.renderLods(accessor.levelWrapper,
accessor.mcModelViewMatrix,
accessor.mcProjectionMatrix,
accessor.partialTicks);
}
}
@Unique SodiumAccessor accessor = null;
@Inject(remap = false, method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/ShaderChunkRenderer;begin(Lme/jellysquid/mods/sodium/client/render/chunk/terrain/TerrainRenderPass;)V", shift = At.Shift.AFTER))
private void injectDHLoDRendering(ChunkRenderMatrices matrices, CommandList commandList, RenderRegionManager regions, SortedRenderLists renderLists, TerrainRenderPass renderPass, ChunkCameraContext camera, CallbackInfo ci)
{
if (accessor == null)
{
accessor = (SodiumAccessor) ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
}
if (renderPass.equals(DefaultTerrainRenderPasses.SOLID))
{
//TODO: use matrices.modelView() and matrices.projection() instead of
// SodiumAccessor.mcModelViewMatrix,
// SodiumAccessor.mcProjectionMatrix,
ClientApi.INSTANCE.renderLods(accessor.levelWrapper,
accessor.mcModelViewMatrix,
accessor.mcProjectionMatrix,
accessor.partialTicks);
}
}
}
#elif POST_MC_1_17_1
// Sodium 0.3 to 0.4
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
@@ -68,29 +70,29 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RegionChunkRenderer.class)
public class MixinSodiumRenderer
public class MixinSodiumRenderer
{
@Unique SodiumAccessor accessor = null;
@Inject(remap = false, method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/ShaderChunkRenderer;begin(Lme/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass;)V", shift = At.Shift.AFTER))
private void injectDHLoDRendering(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderList list, BlockRenderPass pass, ChunkCameraContext camera, CallbackInfo ci)
{
if (accessor == null)
@Unique SodiumAccessor accessor = null;
@Inject(remap = false, method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/ShaderChunkRenderer;begin(Lme/jellysquid/mods/sodium/client/render/chunk/passes/BlockRenderPass;)V", shift = At.Shift.AFTER))
private void injectDHLoDRendering(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderList list, BlockRenderPass pass, ChunkCameraContext camera, CallbackInfo ci)
{
if (accessor == null)
{
accessor = (SodiumAccessor)ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
}
if (pass.equals(BlockRenderPass.SOLID))
accessor = (SodiumAccessor) ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
}
if (pass.equals(BlockRenderPass.SOLID))
{
//TODO: use matrices.modelView() and matrices.projection() instead of
// SodiumAccessor.mcModelViewMatrix,
// SodiumAccessor.mcProjectionMatrix,
ClientApi.INSTANCE.renderLods(accessor.levelWrapper,
accessor.mcModelViewMatrix,
accessor.mcProjectionMatrix,
accessor.partialTicks);
}
}
//TODO: use matrices.modelView() and matrices.projection() instead of
// SodiumAccessor.mcModelViewMatrix,
// SodiumAccessor.mcProjectionMatrix,
ClientApi.INSTANCE.renderLods(accessor.levelWrapper,
accessor.mcModelViewMatrix,
accessor.mcProjectionMatrix,
accessor.partialTicks);
}
}
}
@@ -16,7 +16,7 @@
* 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.fabric.mixins.server;
import org.spongepowered.asm.mixin.Mixin;
@@ -33,23 +33,28 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.WorldgenRandom;
@Mixin(ChunkGenerator.class)
public class MixinChunkGenerator {
@Redirect(method = "applyBiomeDecoration", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/biome/Biome;generate(Lnet/minecraft/world/level/StructureFeatureManager;"
+ "Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/server/level/WorldGenRegion;J"
+ "Lnet/minecraft/world/level/levelgen/WorldgenRandom;Lnet/minecraft/core/BlockPos;)V"
))
private void wrapBiomeGenerateCall(Biome biome, StructureFeatureManager structFeatManager, ChunkGenerator generator,
WorldGenRegion genRegion, long l, WorldgenRandom random, BlockPos pos) {
synchronized(ChunkGenerator.class) {
biome.generate(structFeatManager, (ChunkGenerator)(Object)this, genRegion, l, random, pos);
}
}
public class MixinChunkGenerator
{
@Redirect(method = "applyBiomeDecoration", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/biome/Biome;generate(Lnet/minecraft/world/level/StructureFeatureManager;"
+ "Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/server/level/WorldGenRegion;J"
+ "Lnet/minecraft/world/level/levelgen/WorldgenRandom;Lnet/minecraft/core/BlockPos;)V"
))
private void wrapBiomeGenerateCall(
Biome biome, StructureFeatureManager structFeatManager, ChunkGenerator generator,
WorldGenRegion genRegion, long l, WorldgenRandom random, BlockPos pos)
{
synchronized (ChunkGenerator.class)
{
biome.generate(structFeatManager, (ChunkGenerator) (Object) this, genRegion, l, random, pos);
}
}
}
#else
@Mixin(ChunkGenerator.class)
public class MixinChunkGenerator {}
public class MixinChunkGenerator { }
#endif
@@ -15,21 +15,22 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ChunkMap.class)
public class MixinChunkMap {
@Unique
private static final String CHUNK_SERIALIZER_WRITE
= "Lnet/minecraft/world/level/chunk/storage/ChunkSerializer;write(" +
"Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;)" +
"Lnet/minecraft/nbt/CompoundTag;";
@Shadow
@Final
ServerLevel level;
@Inject(method = "save", at = @At(value = "INVOKE", target = CHUNK_SERIALIZER_WRITE))
private void onChunkSave(ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
{
public class MixinChunkMap
{
@Unique
private static final String CHUNK_SERIALIZER_WRITE
= "Lnet/minecraft/world/level/chunk/storage/ChunkSerializer;write(" +
"Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/chunk/ChunkAccess;)" +
"Lnet/minecraft/nbt/CompoundTag;";
@Shadow
@Final
ServerLevel level;
@Inject(method = "save", at = @At(value = "INVOKE", target = CHUNK_SERIALIZER_WRITE))
private void onChunkSave(ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
{
#if MC_1_16_5
if (chunk.getBiomes() == null)
{
@@ -38,11 +39,11 @@ public class MixinChunkMap {
}
#endif
ServerApi.INSTANCE.serverChunkSaveEvent(
new ChunkWrapper(chunk, level, ServerLevelWrapper.getWrapper(level)),
ServerLevelWrapper.getWrapper(level)
);
}
ServerApi.INSTANCE.serverChunkSaveEvent(
new ChunkWrapper(chunk, level, ServerLevelWrapper.getWrapper(level)),
ServerLevelWrapper.getWrapper(level)
);
}
}
@@ -16,7 +16,7 @@
* 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.fabric.mixins.server;
import java.util.concurrent.ExecutorService;
@@ -35,10 +35,11 @@ import net.minecraft.Util;
@Mixin(Util.class)
public class MixinUtilBackgroundThread
{
private static boolean shouldApplyOverride() {
private static boolean shouldApplyOverride()
{
return FabricServerProxy.isGenerationThreadChecker != null && FabricServerProxy.isGenerationThreadChecker.get();
}
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
{
@@ -48,7 +49,7 @@ public class MixinUtilBackgroundThread
ci.setReturnValue(new DummyRunExecutorService());
}
}
#if POST_MC_1_17_1
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
at = @At("HEAD"), cancellable = true)
@@ -73,5 +74,5 @@ public class MixinUtilBackgroundThread
}
}
#endif
}
@@ -16,7 +16,7 @@
* 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.fabric.mixins.server.unsafe;
import org.spongepowered.asm.mixin.Mixin;
@@ -38,15 +38,18 @@ import java.util.concurrent.Semaphore;
* FIXME: Recheck this
*/
@Mixin(ThreadingDetector.class)
public class MixinThreadingDetector {
@Mutable
@Shadow
private Semaphore lock;
@Inject(method = "<init>", at = @At("RETURN"))
private void setSemaphore(CallbackInfo ci) {
this.lock = new Semaphore(2);
}
public class MixinThreadingDetector
{
@Mutable
@Shadow
private Semaphore lock;
@Inject(method = "<init>", at = @At("RETURN"))
private void setSemaphore(CallbackInfo ci)
{
this.lock = new Semaphore(2);
}
}
#else
@@ -16,7 +16,7 @@
* 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.fabric.wrappers;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
@@ -28,18 +28,21 @@ import com.seibel.distanthorizons.fabric.wrappers.modAccessor.ModChecker;
* can access them in Core. <br>
* This needs to be called before any Core classes
* are loaded.
*
*
* @author James Seibel
* @author Ran
* @version 3-5-2022
*/
public class FabricDependencySetup
{
public static void createInitialBindings() {
public static void createInitialBindings()
{
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
}
public static void runDelayedSetup() {
public static void runDelayedSetup()
{
SingletonInjector.INSTANCE.runDelayedSetup();
}
}
@@ -16,7 +16,7 @@
* 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.fabric.wrappers.config;
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
@@ -26,10 +26,13 @@ import com.terraformersmc.modmenu.api.ModMenuApi;
/**
* For making the config show up in modmenu
*/
public class ModMenuIntegration implements ModMenuApi {
// For the custom config code
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> GetConfigScreen.getScreen(parent);
}
public class ModMenuIntegration implements ModMenuApi
{
// For the custom config code
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory()
{
return parent -> GetConfigScreen.getScreen(parent);
}
}
@@ -12,16 +12,17 @@ import org.betterx.bclib.config.Configs;
public class BCLibAccessor implements IBCLibAccessor
{
@Override
public String getModName() { return "BCLib"; }
public void setRenderCustomFog(boolean newValue)
{
@Override
public String getModName() { return "BCLib"; }
public void setRenderCustomFog(boolean newValue)
{
#if MC_1_16_5 || MC_1_17_1
#elif PRE_MC_1_19_2
// Change the value of CUSTOM_FOG_RENDERING in the bclib client config
// This disabled fog from rendering within bclib
Configs.CLIENT_CONFIG.set(ClientConfig.CUSTOM_FOG_RENDERING, newValue);
// Change the value of CUSTOM_FOG_RENDERING in the bclib client config
// This disabled fog from rendering within bclib
Configs.CLIENT_CONFIG.set(ClientConfig.CUSTOM_FOG_RENDERING, newValue);
#endif
}
}
}
@@ -2,11 +2,14 @@ package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
public class ImmersivePortalsAccessor implements IImmersivePortalsAccessor {
@Override
public String getModName() {
return "ImmersivePortals-Fabric";
}
public float partialTicks;
public class ImmersivePortalsAccessor implements IImmersivePortalsAccessor
{
@Override
public String getModName()
{
return "ImmersivePortals-Fabric";
}
public float partialTicks;
}
@@ -16,17 +16,20 @@
* 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.fabric.wrappers.modAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import net.fabricmc.loader.api.FabricLoader;
public class ModChecker implements IModChecker {
public static final ModChecker INSTANCE = new ModChecker();
@Override
public boolean isModLoaded(String modid) {
return FabricLoader.getInstance().isModLoaded(modid);
}
public class ModChecker implements IModChecker
{
public static final ModChecker INSTANCE = new ModChecker();
@Override
public boolean isModLoaded(String modid)
{
return FabricLoader.getInstance().isModLoaded(modid);
}
}
@@ -16,7 +16,7 @@
* 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.fabric.wrappers.modAccessor;
import java.util.HashSet;
@@ -26,13 +26,13 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOpt
public class OptifineAccessor extends AbstractOptifineAccessor
{
@Override
public String getModName()
{
return "Optifine-Fabric-1.18.X";
}
@Override
public HashSet<DhChunkPos> getNormalRenderedChunks()
{
@@ -16,7 +16,7 @@
* 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.fabric.wrappers.modAccessor;
import java.util.HashSet;
@@ -44,45 +44,48 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.level.LevelHeightAccessor;
#endif
public class SodiumAccessor implements ISodiumAccessor {
public class SodiumAccessor implements ISodiumAccessor
{
private final IWrapperFactory factory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
private final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
public IClientLevelWrapper levelWrapper;
public Mat4f mcModelViewMatrix;
public Mat4f mcProjectionMatrix;
public float partialTicks;
@Override
public String getModName() {
public String getModName()
{
return "Sodium-Fabric";
}
#if POST_MC_1_17_1
@Override
public HashSet<DhChunkPos> getNormalRenderedChunks() {
public HashSet<DhChunkPos> getNormalRenderedChunks()
{
SodiumWorldRenderer renderer = SodiumWorldRenderer.instance();
LevelHeightAccessor height = Minecraft.getInstance().level;
LevelHeightAccessor height = Minecraft.getInstance().level;
#if POST_MC_1_20_1
// TODO: This is just a tmp solution, use a proper solution later
return MC_RENDER.getMaximumRenderedChunks().stream().filter((DhChunkPos chunk) -> {
return (renderer.isBoxVisible(
chunk.getMinBlockX()+1, height.getMinBuildHeight()+1, chunk.getMinBlockZ()+1,
chunk.getMinBlockX()+15, height.getMaxBuildHeight()-1, chunk.getMinBlockZ()+15));
chunk.getMinBlockX() + 1, height.getMinBuildHeight() + 1, chunk.getMinBlockZ() + 1,
chunk.getMinBlockX() + 15, height.getMaxBuildHeight() - 1, chunk.getMinBlockZ() + 15));
}).collect(Collectors.toCollection(HashSet::new));
#elif POST_MC_1_18_2
// 0b11 = Lighted chunk & loaded chunk
return renderer.getChunkTracker().getChunks(0b00).filter(
(long l) -> {
return true;
}).mapToObj(DhChunkPos::new).collect(Collectors.toCollection(HashSet::new));
(long l) -> {
return true;
}).mapToObj(DhChunkPos::new).collect(Collectors.toCollection(HashSet::new));
#else
// TODO: Maybe use a mixin to make this more efficient, and maybe ignore changes behind the camera
return MC_RENDER.getMaximumRenderedChunks().stream().filter((DhChunkPos chunk) -> {
return (renderer.isBoxVisible(
chunk.getMinBlockX()+1, height.getMinBuildHeight()+1, chunk.getMinBlockZ()+1,
chunk.getMinBlockX()+15, height.getMaxBuildHeight()-1, chunk.getMinBlockZ()+15));
chunk.getMinBlockX() + 1, height.getMinBuildHeight() + 1, chunk.getMinBlockZ() + 1,
chunk.getMinBlockX() + 15, height.getMaxBuildHeight() - 1, chunk.getMinBlockZ() + 15));
}).collect(Collectors.toCollection(HashSet::new));
#endif
}
@@ -125,13 +128,15 @@ public class SodiumAccessor implements ISodiumAccessor {
}
}
#endif
/** A temporary overwrite for a config in sodium 0.5 to fix their terrain from showing, will be removed once a proper fix is added */
// FIXME
@Override
public void setFogOcclusion(boolean b) {
public void setFogOcclusion(boolean b)
{
#if POST_MC_1_20_1
me.jellysquid.mods.sodium.client.SodiumClientMod.options().performance.useFogOcclusion = b;
#endif
}
}
@@ -16,20 +16,24 @@
* 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.fabric.wrappers.modAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
public class StarlightAccessor implements IStarlightAccessor {
public class StarlightAccessor implements IStarlightAccessor
{
@Override
public String getModName() {
public String getModName()
{
return "Starlight-Fabric-1.18.X";
}
public StarlightAccessor() {
public StarlightAccessor()
{
}
}
@@ -60,7 +60,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
/**
* 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
*/
@@ -68,7 +68,7 @@ public class ForgeClientProxy
{
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
// private static SimpleChannel multiversePluginChannel;
@@ -213,7 +213,7 @@ public class ForgeClientProxy
if (GetLevel(event) instanceof ClientLevel)
{
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk() , GetLevel(event), wrappedLevel);
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetLevel(event), wrappedLevel);
ClientApi.INSTANCE.clientChunkSaveEvent(chunk, ClientLevelWrapper.getWrapper((ClientLevel) GetLevel(event)));
}
}
@@ -66,6 +66,7 @@ import org.apache.logging.log4j.Logger;
// these imports change due to forge refactoring classes in 1.19
#if PRE_MC_1_19_2
import net.minecraftforge.client.model.data.ModelDataMap;
import java.util.Random;
#else
import net.minecraft.util.RandomSource;
@@ -92,7 +93,7 @@ public class ForgeMain implements LodForgeMethodCaller
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
public static ForgeClientProxy client_proxy = null;
public static ForgeServerProxy server_proxy = null;
public ForgeMain()
{
DependencySetup.createClientBindings();
@@ -103,27 +104,28 @@ public class ForgeMain implements LodForgeMethodCaller
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::initClient);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::initDedicated);
}
private void initClient(final FMLClientSetupEvent event)
{
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
LOGGER.info("Initializing Mod");
LodCommonMain.startup(this);
ForgeDependencySetup.createInitialBindings();
LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
// Print git info (Useful for dev builds)
LOGGER.info("DH Branch: "+ ModGitInfo.Git_Main_Branch);
LOGGER.info("DH Commit: "+ ModGitInfo.Git_Main_Commit);
LOGGER.info("DH-Core Commit: "+ ModGitInfo.Git_Core_Commit);
LOGGER.info("DH Branch: " + ModGitInfo.Git_Main_Branch);
LOGGER.info("DH Commit: " + ModGitInfo.Git_Main_Commit);
LOGGER.info("DH-Core Commit: " + ModGitInfo.Git_Core_Commit);
client_proxy = new ForgeClientProxy();
MinecraftForge.EVENT_BUS.register(client_proxy);
server_proxy = new ForgeServerProxy(false);
MinecraftForge.EVENT_BUS.register(server_proxy);
if (ReflectionHandler.INSTANCE.optifinePresent()) {
if (ReflectionHandler.INSTANCE.optifinePresent())
{
ModAccessorInjector.INSTANCE.bind(IOptifineAccessor.class, new OptifineAccessor());
}
@@ -141,14 +143,14 @@ public class ForgeMain implements LodForgeMethodCaller
ForgeClientProxy.setupNetworkingListeners(event);
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
// Init config
// The reason im initialising in this rather than the post init process is cus im using this for the auto updater
LodCommonMain.initConfig();
}
private void initDedicated(final FMLDedicatedServerSetupEvent event)
{
// DependencySetup.createServerBindings();
@@ -159,39 +161,43 @@ public class ForgeMain implements LodForgeMethodCaller
//
postInitCommon();
}
private void postInitCommon()
{
LOGGER.info("Post-Initializing Mod");
ForgeDependencySetup.runDelayedSetup();
LOGGER.info("Mod Post-Initialized");
}
#if PRE_MC_1_19_2
private final ModelDataMap modelData = new ModelDataMap.Builder().build();
#else
private final ModelData modelData = ModelData.EMPTY;
#endif
@Override
#if PRE_MC_1_19_2
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random)
{
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, modelData);
}
#else
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, RandomSource random) {
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, modelData #if POST_MC_1_19_2, RenderType.solid() #endif);
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, RandomSource random)
{
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, modelData #if POST_MC_1_19_2 , RenderType.solid() #endif );
}
#endif
@Override //TODO: Check this if its still needed
public int colorResolverGetColor(ColorResolver resolver, Biome biome, double x, double z) {
public int colorResolverGetColor(ColorResolver resolver, Biome biome, double x, double z)
{
#if MC_1_17_1______Still_needed
return resolver.m_130045_(biome, x, z);
#else
return resolver.getColor(biome, x, z);
#endif
}
}
@@ -38,38 +38,38 @@ import java.util.function.Supplier;
public class ForgeServerProxy
{
#if PRE_MC_1_19_2
private static LevelAccessor GetLevel(WorldEvent e) { return e.getWorld(); }
#else
private static LevelAccessor GetLevel(LevelEvent e) { return e.getLevel(); }
#if PRE_MC_1_19_2
private static LevelAccessor GetLevel(WorldEvent e) { return e.getWorld(); }
#else
private static LevelAccessor GetLevel(LevelEvent e) { return e.getLevel(); }
#endif
private final ServerApi serverApi = ServerApi.INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicated;
public static Supplier<Boolean> isGenerationThreadChecker = null;
public ForgeServerProxy(boolean isDedicated)
private final ServerApi serverApi = ServerApi.INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicated;
public static Supplier<Boolean> isGenerationThreadChecker = null;
public ForgeServerProxy(boolean isDedicated)
{
this.isDedicated = isDedicated;
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
}
private boolean isValidTime()
private boolean isValidTime()
{
if (this.isDedicated)
{
return true;
}
//FIXME: This may cause init issue...
return !(Minecraft.getInstance().screen instanceof TitleScreen);
}
private ServerLevelWrapper getLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
// ServerTickEvent (at end)
@SubscribeEvent
public void serverTickEvent(TickEvent.ServerTickEvent event)
private ServerLevelWrapper getLevelWrapper(ServerLevel level) { return ServerLevelWrapper.getWrapper(level); }
// ServerTickEvent (at end)
@SubscribeEvent
public void serverTickEvent(TickEvent.ServerTickEvent event)
{
if (event.phase == TickEvent.Phase.END)
{
@@ -79,81 +79,86 @@ public class ForgeServerProxy
}
}
}
// ServerWorldLoadEvent
@SubscribeEvent
public void dedicatedWorldLoadEvent(#if MC_1_16_5 || MC_1_17_1 FMLServerAboutToStartEvent #else ServerAboutToStartEvent #endif event)
// ServerWorldLoadEvent
@SubscribeEvent
public void dedicatedWorldLoadEvent(#if MC_1_16_5 || MC_1_17_1 FMLServerAboutToStartEvent #else ServerAboutToStartEvent #endif event)
{
if (this.isValidTime())
{
this.serverApi.serverLoadEvent(this.isDedicated);
}
}
// ServerWorldUnloadEvent
@SubscribeEvent
public void serverWorldUnloadEvent(#if MC_1_16_5 || MC_1_17_1 FMLServerStoppingEvent #else ServerStoppingEvent #endif event)
// ServerWorldUnloadEvent
@SubscribeEvent
public void serverWorldUnloadEvent(#if MC_1_16_5 || MC_1_17_1 FMLServerStoppingEvent #else ServerStoppingEvent #endif event)
{
if (this.isValidTime())
{
this.serverApi.serverUnloadEvent();
}
}
// ServerLevelLoadEvent
@SubscribeEvent
// ServerLevelLoadEvent
@SubscribeEvent
#if PRE_MC_1_19_2
public void serverLevelLoadEvent(WorldEvent.Load event)
#else
public void serverLevelLoadEvent(LevelEvent.Load event)
public void serverLevelLoadEvent(LevelEvent.Load event)
#endif
{
if (isValidTime()) {
if (GetLevel(event) instanceof ServerLevel) {
serverApi.serverLevelLoadEvent(getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
// ServerLevelUnloadEvent
@SubscribeEvent
{
if (isValidTime())
{
if (GetLevel(event) instanceof ServerLevel)
{
serverApi.serverLevelLoadEvent(getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
// ServerLevelUnloadEvent
@SubscribeEvent
#if PRE_MC_1_19_2
public void serverLevelUnloadEvent(WorldEvent.Unload event)
#else
public void serverLevelUnloadEvent(LevelEvent.Unload event)
public void serverLevelUnloadEvent(LevelEvent.Unload event)
#endif
{
if (isValidTime()) {
if (GetLevel(event) instanceof ServerLevel) {
serverApi.serverLevelUnloadEvent(getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
@SubscribeEvent
public void serverChunkLoadEvent(ChunkEvent.Load event)
{
if (this.isValidTime())
{
if (GetLevel(event) instanceof ServerLevel)
{
ServerLevelWrapper wrappedLevel = ServerLevelWrapper.getWrapper((ServerLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetLevel(event), wrappedLevel);
this.serverApi.serverChunkLoadEvent(chunk, this.getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
@SubscribeEvent
public void serverChunkSaveEvent(ChunkEvent.Unload event)
{
if (this.isValidTime())
{
if (isValidTime())
{
if (GetLevel(event) instanceof ServerLevel)
if (GetLevel(event) instanceof ServerLevel)
{
ServerLevelWrapper wrappedLevel = ServerLevelWrapper.getWrapper((ServerLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetLevel(event), wrappedLevel);
this.serverApi.serverChunkSaveEvent(chunk, this.getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
serverApi.serverLevelUnloadEvent(getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
@SubscribeEvent
public void serverChunkLoadEvent(ChunkEvent.Load event)
{
if (this.isValidTime())
{
if (GetLevel(event) instanceof ServerLevel)
{
ServerLevelWrapper wrappedLevel = ServerLevelWrapper.getWrapper((ServerLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetLevel(event), wrappedLevel);
this.serverApi.serverChunkLoadEvent(chunk, this.getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
@SubscribeEvent
public void serverChunkSaveEvent(ChunkEvent.Unload event)
{
if (this.isValidTime())
{
if (GetLevel(event) instanceof ServerLevel)
{
ServerLevelWrapper wrappedLevel = ServerLevelWrapper.getWrapper((ServerLevel) GetLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetLevel(event), wrappedLevel);
this.serverApi.serverChunkSaveEvent(chunk, this.getLevelWrapper((ServerLevel) GetLevel(event)));
}
}
}
}
@@ -12,50 +12,60 @@ import java.util.Set;
* @author coolGi
* @author cortex
*/
public class ForgeMixinPlugin implements IMixinConfigPlugin {
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (mixinClassName.contains(".mods.")) { // If the mixin wants to go into a mod then we check if that mod is loaded or not
return ModList.get().isLoaded(
mixinClassName
// What these 2 regex's do is get the mod name that we are checking out of the mixinClassName
// Eg. "com.seibel.distanthorizons.mixins.mods.sodium.MixinSodiumChunkRenderer" turns into "sodium"
.replaceAll("^.*mods.", "") // Replaces everything before the mods
.replaceAll("\\..*$", "") // Replaces everything after the mod name
);
}
return true;
}
@Override
public void onLoad(String mixinPackage) {
}
@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 targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
public class ForgeMixinPlugin implements IMixinConfigPlugin
{
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
{
if (mixinClassName.contains(".mods."))
{ // If the mixin wants to go into a mod then we check if that mod is loaded or not
return ModList.get().isLoaded(
mixinClassName
// What these 2 regex's do is get the mod name that we are checking out of the mixinClassName
// Eg. "com.seibel.distanthorizons.mixins.mods.sodium.MixinSodiumChunkRenderer" turns into "sodium"
.replaceAll("^.*mods.", "") // Replaces everything before the mods
.replaceAll("\\..*$", "") // Replaces everything after the mod name
);
}
return true;
}
@Override
public void onLoad(String mixinPackage)
{
}
@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 targetClass, String mixinClassName, IMixinInfo mixinInfo)
{
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo)
{
}
}
@@ -12,13 +12,13 @@ public class MixinClientPacketListener
{
// TODO update fabric version as well
@Inject(method = "handleLogin", at = @At("HEAD"))
void onHandleLoginStart(CallbackInfo ci)
{
// not the best way to notify Core that we are no longer in the previous world, but it will have to do for now
ClientApi.INSTANCE.onClientOnlyDisconnected();
}
@Inject(method = "handleLogin", at = @At("RETURN"))
void onHandleLoginEnd(CallbackInfo ci) { ClientApi.INSTANCE.onClientOnlyConnected(); }
@Inject(method = "handleLogin", at = @At("HEAD"))
void onHandleLoginStart(CallbackInfo ci)
{
// not the best way to notify Core that we are no longer in the previous world, but it will have to do for now
ClientApi.INSTANCE.onClientOnlyDisconnected();
}
@Inject(method = "handleLogin", at = @At("RETURN"))
void onHandleLoginEnd(CallbackInfo ci) { ClientApi.INSTANCE.onClientOnlyConnected(); }
}
@@ -10,12 +10,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(DebugScreenOverlay.class)
public class MixinDebugScreenOverlay {
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void addCustomF3(CallbackInfoReturnable<List<String>> cir) {
List<String> messages = cir.getReturnValue();
F3Screen.addStringToDisplay(messages);
}
public class MixinDebugScreenOverlay
{
@Inject(method = "getSystemInformation", at = @At("RETURN"))
private void addCustomF3(CallbackInfoReturnable<List<String>> cir)
{
List<String> messages = cir.getReturnValue();
F3Screen.addStringToDisplay(messages);
}
}
@@ -42,15 +42,16 @@ import net.minecraft.world.level.material.FogType;
@Mixin(FogRenderer.class)
public class MixinFogRenderer {
public class MixinFogRenderer
{
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"),
method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V",
remap = #if MC_1_17_1 || MC_1_18_2 false #else true #endif) // Remap messiness due to this being weird in forge
remap = #if MC_1_17_1 || MC_1_18_2 false #else true #endif ) // Remap messiness due to this being weird in forge
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float partTick, CallbackInfo callback)
{
#if PRE_MC_1_17_1
@@ -76,4 +77,5 @@ public class MixinFogRenderer {
#endif
}
}
}
@@ -16,27 +16,31 @@ public class MixinGameRenderer
{
private static final Logger LOGGER = LogManager.getLogger(MixinGameRenderer.class.getSimpleName());
#if POST_MC_1_17_1
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci) {
LOGGER.info("Starting up renderer (forge)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
#if POST_MC_1_17_1
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci)
{
LOGGER.info("Starting up renderer (forge)");
if (!DependencySetupDoneCheck.isDone)
{
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
@Inject(method = "shutdownShaders", at = @At("HEAD"))
public void onShutdownShaders(CallbackInfo ci) {
LOGGER.info("Shutting down renderer (forge)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
public void onShutdownShaders(CallbackInfo ci)
{
LOGGER.info("Shutting down renderer (forge)");
if (!DependencySetupDoneCheck.isDone)
{
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
#else
@@ -71,12 +71,13 @@ public class MixinLevelRenderer
private ClientLevel level;
@Unique
private static float previousPartialTicks = 0;
// TODO: Is there any reason why this is here? Can it be deleted?
public MixinLevelRenderer() {
public MixinLevelRenderer()
{
throw new NullPointerException("Null cannot be cast to non-null type.");
}
#if PRE_MC_1_17_1
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/vertex/PoseStack;F)V")
private void renderSky(PoseStack matrixStackIn, float partialTicks, CallbackInfo callback)
@@ -98,10 +99,10 @@ public class MixinLevelRenderer
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
#elif PRE_MC_1_19_4
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
#else
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V",
@@ -147,38 +148,38 @@ public class MixinLevelRenderer
}
}
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
{
callback.cancel();
}
}
@Redirect(method =
"Lnet/minecraft/client/renderer/LevelRenderer;" +
"renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;" +
"FJZLnet/minecraft/client/Camera;" +
"Lnet/minecraft/client/renderer/GameRenderer;" +
"Lnet/minecraft/client/renderer/LightTexture;" +
"Lnet/minecraft/client/renderer/LevelRenderer;" +
"renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;" +
"FJZLnet/minecraft/client/Camera;" +
"Lnet/minecraft/client/renderer/GameRenderer;" +
"Lnet/minecraft/client/renderer/LightTexture;" +
#if PRE_MC_1_19_4
"Lcom/mojang/math/Matrix4f;)V"
#else
"Lorg/joml/Matrix4f;)V"
#endif
,
at = @At(
value = "INVOKE",
#if PRE_MC_1_20_1
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"
#else
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"
#endif
))
private int callAfterRunUpdates(LevelLightEngine light #if PRE_MC_1_20_1 , int pos, boolean isQueueEmpty, boolean updateBlockLight #endif)
"Lcom/mojang/math/Matrix4f;)V"
#else
"Lorg/joml/Matrix4f;)V"
#endif
,
at = @At(
value = "INVOKE",
#if PRE_MC_1_20_1
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runUpdates(IZZ)I"
#else
target = "Lnet/minecraft/world/level/lighting/LevelLightEngine;runLightUpdates()I"
#endif
))
private int callAfterRunUpdates(LevelLightEngine light #if PRE_MC_1_20_1 , int pos, boolean isQueueEmpty, boolean updateBlockLight #endif )
{
#if PRE_MC_1_20_1
int r = light.runUpdates(pos, isQueueEmpty, updateBlockLight);
#else
int r = light.runLightUpdates();
int r = light.runLightUpdates();
#endif
ChunkWrapper.syncedUpdateClientLightStatus();
return r;
@@ -12,16 +12,19 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LightTexture.class)
public class MixinLightmap {
@Shadow
@Final
public NativeImage lightPixels;
@Inject(method="updateLightTexture", at=@At(
value="INVOKE",
target="Lnet/minecraft/client/renderer/texture/DynamicTexture;upload()V"))
public void updateLightTexture(float f, CallbackInfo ci) {
//ApiShared.LOGGER.info("Lightmap update");
MinecraftRenderWrapper.INSTANCE.updateLightmap(lightPixels);
}
public class MixinLightmap
{
@Shadow
@Final
public NativeImage lightPixels;
@Inject(method = "updateLightTexture", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;upload()V"))
public void updateLightTexture(float f, CallbackInfo ci)
{
//ApiShared.LOGGER.info("Lightmap update");
MinecraftRenderWrapper.INSTANCE.updateLightmap(lightPixels);
}
}
@@ -23,31 +23,36 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Minecraft.class)
public class MixinMinecraft
{
@Redirect(
method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
)
public void onOpenScreen(Minecraft instance, Screen guiScreen)
@Redirect(
method = "<init>(Lnet/minecraft/client/main/GameConfig;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V")
)
public void onOpenScreen(Minecraft instance, Screen guiScreen)
{
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
{
// Don't do anything if the user doesn't want it
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
return;
}
if (SelfUpdater.onStart()) {
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion())
));
} else {
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
}
}
@Inject(at = @At("HEAD"), method = "close()V", remap = false)
public void close(CallbackInfo ci) {
SelfUpdater.onClose();
}
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
return;
}
if (SelfUpdater.onStart())
{
instance.setScreen(new UpdateModScreen(
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion())
));
}
else
{
instance.setScreen(guiScreen); // Sets the screen back to the vanilla screen as if nothing ever happened
}
}
@Inject(at = @At("HEAD"), method = "close()V", remap = false)
public void close(CallbackInfo ci)
{
SelfUpdater.onClose();
}
}
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.forge.mixins.client;
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
@@ -44,34 +44,38 @@ import java.util.Objects;
* @version 12-02-2021
*/
@Mixin(OptionsScreen.class)
public class MixinOptionsScreen extends Screen {
// Get the texture for the button
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID,"textures/gui/button.png");
protected MixinOptionsScreen(Component title) {
super(title);
}
@Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) {
if (Config.Client.optionsButton.get())
this. #if PRE_MC_1_17_1 addButton #else addRenderableWidget #endif
(new TexturedButtonWidget(
// 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
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
// Add a title to the button
public class MixinOptionsScreen extends Screen
{
// Get the texture for the button
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
protected MixinOptionsScreen(Component title)
{
super(title);
}
@Inject(at = @At("HEAD"), method = "init")
private void lodconfig$init(CallbackInfo ci)
{
if (Config.Client.optionsButton.get())
this. #if PRE_MC_1_17_1 addButton #else addRenderableWidget #endif
(new TexturedButtonWidget(
// 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
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(GetConfigScreen.getScreen(this)),
// Add a title to the button
#if PRE_MC_1_19_2
new TranslatableComponent(ModInfo.ID + ".title")));
new TranslatableComponent(ModInfo.ID + ".title")));
#else
Component.translatable(ModInfo.ID + ".title")));
Component.translatable(ModInfo.ID + ".title")));
#endif
}
}
}
@@ -15,16 +15,17 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(TextureUtil.class)
public class MixinTextureUtil
{
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap=false)
private static void setLodBias(int target, int pname, float param)
@Redirect(method = "prepareImage(Lcom/mojang/blaze3d/platform/NativeImage$InternalGlFormat;IIII)V",
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V"), remap = false)
private static void setLodBias(int target, int pname, float param)
{
float biasValue = Config.Client.Advanced.Graphics.AdvancedGraphics.lodBias.get().floatValue();
if (biasValue != 0)
float biasValue = Config.Client.Advanced.Graphics.AdvancedGraphics.lodBias.get().floatValue();
if (biasValue != 0)
{
// The target is GL11.GL_TEXTURE_2D
// And the pname is GL14.GL_TEXTURE_LOD_BIAS
GlStateManager._texParameter(target, pname, biasValue);
}
}
// The target is GL11.GL_TEXTURE_2D
// And the pname is GL14.GL_TEXTURE_LOD_BIAS
GlStateManager._texParameter(target, pname, biasValue);
}
}
}

Some files were not shown because too many files have changed in this diff Show More