Merge branch 'main' into removeArch

This commit is contained in:
James Seibel
2024-02-17 09:25:34 -06:00
15 changed files with 182 additions and 84 deletions
+8 -1
View File
@@ -199,6 +199,12 @@ subprojects { p ->
implementation("org.apache.logging.log4j:log4j-api:${rootProject.log4j_version}")
implementation("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}")
// JOML
if (project.hasProperty("embed_joml") && embed_joml == "true")
forgeShadowMe("org.joml:joml:${rootProject.joml_version}")
else
implementation("org.joml:joml:${rootProject.joml_version}")
// JUnit tests
implementation("org.junit.jupiter:junit-jupiter:5.8.2")
implementation("org.junit.jupiter:junit-jupiter-engine:5.8.2")
@@ -305,7 +311,8 @@ subprojects { p ->
// relocate "org.sqlite", "${librariesLocation}.sqlite"
// JOML
relocate "org.joml", "${librariesLocation}.joml"
if (project.hasProperty("embed_joml") && embed_joml == "true")
relocate "org.joml", "${librariesLocation}.joml"
// NightConfig (includes Toml & Json)
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
@@ -65,7 +65,7 @@ public class BiomeWrapper implements IBiomeWrapper
#endif
public static final String EMPTY_STRING = "EMPTY";
public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper(null, null);
public static final BiomeWrapper EMPTY_WRAPPER = new BiomeWrapper();
/** keep track of broken biomes so we don't log every time */
private static final HashSet<String> brokenResourceLocationStrings = new HashSet<>();
@@ -115,7 +115,6 @@ public class BiomeWrapper implements IBiomeWrapper
return newWrapper;
}
}
private BiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
{
this.biome = biome;
@@ -123,6 +122,13 @@ public class BiomeWrapper implements IBiomeWrapper
LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]");
}
/** should only be used to create {@link BiomeWrapper#EMPTY_WRAPPER} */
private BiomeWrapper()
{
this.biome = null;
this.serialString = EMPTY_STRING;
}
//=========//
@@ -489,6 +489,10 @@ public class BlockStateWrapper implements IBlockStateWrapper
{
return IrisBlockMaterial.LEAVES;
}
else if (this.blockState.is(Blocks.LAVA))
{
return IrisBlockMaterial.LAVA;
}
else if (this.isLiquid() || this.blockState.is(Blocks.WATER))
{
return IrisBlockMaterial.WATER;
@@ -524,10 +528,6 @@ public class BlockStateWrapper implements IBlockStateWrapper
)
{
return IrisBlockMaterial.DIRT;
}
else if (this.blockState.is(Blocks.LAVA))
{
return IrisBlockMaterial.LAVA;
}
#if MC_VER >= MC_1_17_1
else if (this.blockState.getSoundType() == SoundType.DEEPSLATE
@@ -70,6 +70,7 @@ import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.chunk.storage.IOWorker;
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
@@ -381,22 +382,50 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
{
ServerLevel level = this.params.level;
//====================//
// get the chunk data //
//====================//
CompoundTag chunkData = null;
try
{
// Warning: if multiple threads attempt to access this method at the same time,
// it can throw EOFExceptions that are caught and logged by Minecraft
//chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
IOWorker ioWorker = level.getChunkSource().chunkMap.worker;
RegionFileStorage storage = this.params.level.getChunkSource().chunkMap.worker.storage;
RegionFileStorageExternalCache cache = this.getOrCreateRegionFileCache(storage);
chunkData = cache.read(chunkPos);
#if MC_VER <= MC_1_18_2
chunkData = ioWorker.load(chunkPos);
#else
// timeout should prevent locking up the thread if the ioWorker dies or has issues
int maxGetTimeInSec = Config.Client.Advanced.WorldGenerator.worldGenerationTimeoutLengthInSeconds.get();
CompletableFuture<Optional<CompoundTag>> future = ioWorker.loadAsync(chunkPos);
try
{
Optional<CompoundTag> data = future.get(maxGetTimeInSec, TimeUnit.SECONDS);
if (data.isPresent())
{
chunkData = data.get();
}
}
catch (Exception e)
{
LOAD_LOGGER.warn("Unable to get chunk at pos ["+chunkPos+"] after ["+maxGetTimeInSec+"] milliseconds.", e);
future.cancel(true);
}
#endif
}
catch (Exception e)
{
LOAD_LOGGER.error("DistantHorizons: Couldn't load or make chunk " + chunkPos + ". Error: " + e.getMessage(), e);
}
//========================//
// convert the chunk data //
//========================//
if (chunkData == null)
{
return EmptyChunk(level, chunkPos);
@@ -17,6 +17,12 @@ import java.nio.file.Path;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantLock;
/**
* @deprecated should be replaced with net.minecraft.world.level.chunk.storage.IOWorker to
* prevent potential file corruption and issues with the C2ME mod.
* Generally this would be done via (MC ServerLevel) level.getChunkSource().chunkMap.worker#loadAsync()
*/
@Deprecated
public class RegionFileStorageExternalCache implements AutoCloseable
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -32,6 +32,8 @@ import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
@@ -123,17 +125,20 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// if we have access to the server, use the chunk save event instead
if (MC.clientConnectedToDedicatedServer())
{
// Since fabric doesn't have a client-side break-block API event, this is the next best thing
ChunkAccess chunk = level.getChunk(blockPos);
if (chunk != null)
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(blockPos.getX(), blockPos.getZ()))
{
LOGGER.trace("attack block at blockPos: " + blockPos);
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
SharedApi.INSTANCE.chunkBlockChangedEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
);
// Since fabric doesn't have a client-side break-block API event, this is the next best thing
ChunkAccess chunk = level.getChunk(blockPos);
if (chunk != null)
{
LOGGER.trace("attack block at blockPos: " + blockPos);
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
SharedApi.INSTANCE.chunkBlockChangedEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
);
}
}
}
@@ -147,20 +152,23 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// if we have access to the server, use the chunk save event instead
if (MC.clientConnectedToDedicatedServer())
{
// Since fabric doesn't have a client-side place-block API event, this is the next best thing
if (hitResult.getType() == HitResult.Type.BLOCK
&& !hitResult.isInside())
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(hitResult.getBlockPos().getX(), hitResult.getBlockPos().getZ()))
{
ChunkAccess chunk = level.getChunk(hitResult.getBlockPos());
if (chunk != null)
// Since fabric doesn't have a client-side place-block API event, this is the next best thing
if (hitResult.getType() == HitResult.Type.BLOCK
&& !hitResult.isInside())
{
LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos());
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
SharedApi.INSTANCE.chunkBlockChangedEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
);
ChunkAccess chunk = level.getChunk(hitResult.getBlockPos());
if (chunk != null)
{
LOGGER.trace("use block at blockPos: " + hitResult.getBlockPos());
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
SharedApi.INSTANCE.chunkBlockChangedEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
wrappedLevel
);
}
}
}
}
@@ -28,56 +28,66 @@ public class MixinChunkMap
@Final
ServerLevel level;
@Inject(method = "save", at = @At(value = "INVOKE", target = CHUNK_SERIALIZER_WRITE))
// firing at INVOKE causes issues with C2ME and is probably unnecessary since we
// don't need the chunk(s) before MC has finished saving them
@Inject(method = "save", at = @At(value = "RETURN", target = CHUNK_SERIALIZER_WRITE))
private void onChunkSave(ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
{
//=====================================//
// corrupt/incomplete chunk validation //
//=====================================//
// MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks)
// this logic should prevent that from happening
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect())
// true means a chunk was saved to disk
if (ci.getReturnValue())
{
return;
// TODO is this validation necessary since we are checking above if
// the callback return value should state if the chunk was actually saved or not?
// Do we trust it to always be correct?
//=====================================//
// corrupt/incomplete chunk validation //
//=====================================//
// MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks)
// this logic should prevent that from happening
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect())
{
return;
}
#else
if (chunk.isUnsaved() || chunk.isUpgrading() || !chunk.isLightCorrect())
{
return;
}
#endif
//==================//
// biome validation //
//==================//
// some chunks may be missing their biomes, which cause issues when attempting to save them
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
if (chunk.getBiomes() == null)
{
return;
}
#else
try
{
// this will throw an exception if the biomes aren't set up
chunk.getNoiseBiome(0,0,0);
}
catch (Exception e)
{
return;
}
#endif
ServerApi.INSTANCE.serverChunkSaveEvent(
new ChunkWrapper(chunk, this.level, ServerLevelWrapper.getWrapper(this.level)),
ServerLevelWrapper.getWrapper(this.level)
);
}
#else
if (chunk.isUnsaved() || chunk.isUpgrading() || !chunk.isLightCorrect())
{
return;
}
#endif
//==================//
// biome validation //
//==================//
// some chunks may be missing their biomes, which cause issues when attempting to save them
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
if (chunk.getBiomes() == null)
{
return;
}
#else
try
{
// this will throw an exception if the biomes aren't set up
chunk.getNoiseBiome(0,0,0);
}
catch (Exception e)
{
return;
}
#endif
ServerApi.INSTANCE.serverChunkSaveEvent(
new ChunkWrapper(chunk, this.level, ServerLevelWrapper.getWrapper(this.level)),
ServerLevelWrapper.getWrapper(this.level)
);
}
}
@@ -173,6 +173,11 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
@SubscribeEvent
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
return;
}
LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
#if MC_VER < MC_1_19_2
@@ -187,6 +192,11 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
@SubscribeEvent
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
return;
}
LOGGER.trace("break or block attack at blockPos: " + event.getPos());
#if MC_VER < MC_1_19_2
@@ -146,6 +146,11 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
@SubscribeEvent
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
return;
}
LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
@@ -156,6 +161,11 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
@SubscribeEvent
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
return;
}
LOGGER.trace("break or block attack at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
@@ -22,14 +22,22 @@ package com.seibel.distanthorizons.neoforge.wrappers.modAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import net.neoforged.fml.ModList;
import java.io.File;
public class ModChecker implements IModChecker
{
public static final ModChecker INSTANCE = new ModChecker();
@Override
public boolean isModLoaded(String modid)
public boolean isModLoaded(String modid)
{
return ModList.get().isLoaded(modid);
return ModList.get().isLoaded(modid);
}
@Override
public File modLocation(String modid)
{
return ModList.get().getModFileById(modid).getFile().getFilePath().toFile();
}
}
+1
View File
@@ -5,6 +5,7 @@ parchment_version=1.16.5:2022.03.06
compatible_minecraft_versions=["1.16.4", "1.16.5"]
accessWidenerVersion=1_16
builds_for=fabric,forge
embed_joml=true
# Fabric loader
fabric_loader_version=0.14.24
+1
View File
@@ -5,6 +5,7 @@ parchment_version=1.17.1:2021.12.12
compatible_minecraft_versions=["1.17", "1.17.1"]
accessWidenerVersion=1_17
builds_for=fabric,forge
embed_joml=true
# Fabric loader
fabric_loader_version=0.14.24
+1
View File
@@ -5,6 +5,7 @@ parchment_version=1.18.2:2022.11.06
compatible_minecraft_versions=["1.18.2"]
accessWidenerVersion=1_18
builds_for=fabric,forge
embed_joml=true
# Fabric loader
fabric_loader_version=0.14.24
+1
View File
@@ -5,6 +5,7 @@ parchment_version=1.19.2:2022.11.27
compatible_minecraft_versions=["1.19.2"]
accessWidenerVersion=1_19_2
builds_for=fabric,forge
embed_joml=true
# Fabric loader
fabric_loader_version=0.14.24