Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons into serverside

This commit is contained in:
s809
2024-08-24 02:59:56 +05:00
38 changed files with 338 additions and 269 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ build:
stage: build
parallel:
matrix:
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21"]
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21.1"]
script:
# this both runs the unit tests and assembles the code
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
@@ -0,0 +1,85 @@
package com.seibel.distanthorizons.common.commonMixins;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class MixinChunkMapCommon
{
public static void onChunkSave(ServerLevel level, ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
{
// is this position already being updated?
if (SharedApi.isChunkAtChunkPosAlreadyUpdating(chunk.getPos().x, chunk.getPos().z))
{
return;
}
// is this chunk being saved to disk?
boolean savingChunkToDisk = ci.getReturnValue();
// true means a chunk was saved to disk
if (!savingChunkToDisk)
{
return;
}
// TODO are the following validations 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
// submit the update event
ServerApi.INSTANCE.serverChunkSaveEvent(
new ChunkWrapper(chunk, level, ServerLevelWrapper.getWrapper(level)),
ServerLevelWrapper.getWrapper(level)
);
}
}
@@ -155,7 +155,7 @@ public class WrapperFactory implements IWrapperFactory
}
}
#if MC_VER <= MC_1_21
//#if MC_VER <= MC_1_XX_X
else if (objectArray.length == 2)
{
// correct number of parameters from the API
@@ -191,16 +191,7 @@ public class WrapperFactory implements IWrapperFactory
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
#else
// Intentional compiler error to bring attention to the missing wrapper function.
// If you need to work on an unimplemented version but don't have the ability to implement this yet
// you can comment it out, but please don't commit it. Someone will have to implement it.
// After implementing the new version please read this method's javadocs for instructions
// on what other locations also need to be updated, the DhAPI specifically needs to
// be updated to state which objects this method accepts.
not implemented for this version of Minecraft!
#endif
//#endif
}
/**
* Note: when this is updated for different MC versions,
@@ -210,16 +201,13 @@ public class WrapperFactory implements IWrapperFactory
{
String[] expectedClassNames;
#if MC_VER <= MC_1_21
//#if MC_VER <= MC_1_XX_X
expectedClassNames = new String[]
{
ChunkAccess.class.getName(),
"[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing
};
#else
// See preprocessor comment in createChunkWrapper() for full documentation
not implemented for this version of Minecraft!
#endif
//#endif
return createWrapperErrorMessage("Chunk wrapper", expectedClassNames, objectArray);
}
@@ -258,7 +246,7 @@ public class WrapperFactory implements IWrapperFactory
Biome biome = (Biome) objectArray[0];
return BiomeWrapper.getBiomeWrapper(biome, coreLevelWrapper);
#elif MC_VER <= MC_1_21
#else
if (!(objectArray[0] instanceof Holder) || !(((Holder<?>) objectArray[0]).value() instanceof Biome))
{
throw new ClassCastException(createBiomeWrapperErrorMessage(objectArray));
@@ -266,9 +254,6 @@ public class WrapperFactory implements IWrapperFactory
Holder<Biome> biomeHolder = (Holder<Biome>) objectArray[0];
return BiomeWrapper.getBiomeWrapper(biomeHolder, coreLevelWrapper);
#else
// See preprocessor comment in createChunkWrapper() for full documentation (not a typo, check createChunkWrapper()'s else statement for full documentation)
not implemented for this version of Minecraft!
#endif
}
/**
@@ -281,11 +266,8 @@ public class WrapperFactory implements IWrapperFactory
#if MC_VER < MC_1_18_2
expectedClassNames = new String[] { Biome.class.getName() };
#elif MC_VER <= MC_1_21
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
#else
// See preprocessor comment in createChunkWrapper() for full documentation
not implemented for this version of Minecraft!
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
#endif
return createWrapperErrorMessage("Biome wrapper", expectedClassNames, objectArray);
@@ -302,7 +284,7 @@ public class WrapperFactory implements IWrapperFactory
#if MC_VER <= MC_1_21
//#if MC_VER <= MC_1_XX_X
if (objectArray.length != 1)
{
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
@@ -314,10 +296,7 @@ public class WrapperFactory implements IWrapperFactory
BlockState blockState = (BlockState) objectArray[0];
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
#else
// See preprocessor comment in createChunkWrapper() for full documentation (not a typo, check createChunkWrapper()'s else statement for full documentation)
not implemented for this version of Minecraft!
#endif
//#endif
}
/**
* Note: when this is updated for different MC versions,
@@ -329,11 +308,8 @@ public class WrapperFactory implements IWrapperFactory
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
expectedClassNames = new String[] { Biome.class.getName() };
#elif MC_VER <= MC_1_21
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
#else
// See preprocessor comment in createChunkWrapper() for full documentation
not implemented for this version of Minecraft!
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
#endif
return createWrapperErrorMessage("BlockState wrapper", expectedClassNames, objectArray);
@@ -293,7 +293,7 @@ public class BiomeWrapper implements IBiomeWrapper
ResourceLocation resourceLocation;
try
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
resourceLocation = new ResourceLocation(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
#else
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceLocationString.substring(0, separatorIndex), resourceLocationString.substring(separatorIndex + 1));
@@ -497,7 +497,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
ResourceLocation resourceLocation;
try
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
resourceLocation = new ResourceLocation(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
#else
resourceLocation = ResourceLocation.fromNamespaceAndPath(resourceStateString.substring(0, separatorIndex), resourceStateString.substring(separatorIndex + 1));
@@ -309,7 +309,7 @@ public class ChunkWrapper implements IChunkWrapper
public ChunkStatus getStatus() { return getStatus(this.getChunk()); }
public static ChunkStatus getStatus(ChunkAccess chunk)
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
return chunk.getStatus();
#else
return chunk.getPersistedStatus();
@@ -259,7 +259,7 @@ public class ClassicConfigGUI
0, 0,
// Some textuary stuff
0,
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
#else
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
@@ -76,7 +76,7 @@ public class UpdateModScreen extends DhScreen
0, 0,
// Some textuary stuff
0,
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
new ResourceLocation(ModInfo.ID, "logo.png"),
#else
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "logo.png"),
@@ -107,7 +107,7 @@ public class UpdateModScreen extends DhScreen
0, 0,
// Some textuary stuff
0,
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
new ResourceLocation(ModInfo.ID, "textures/gui/changelog.png"),
#else
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/changelog.png"),
@@ -21,7 +21,7 @@ public class MinecraftDedicatedServerWrapper implements IMinecraftSharedWrapper
throw new IllegalStateException("Trying to get Installation Direction before Dedicated server complete initialization!");
}
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
return this.dedicatedServer.getServerDirectory();
#else
return this.dedicatedServer.getServerDirectory().toFile();
@@ -165,7 +165,7 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
if (MC.level.dimensionType().hasSkyLight())
{
float frameTime;
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
frameTime = MC.getFrameTime();
#else
frameTime = MC.getTimer().getRealtimeDeltaTicks();
@@ -85,7 +85,7 @@ import net.minecraft.world.level.material.Fluids;
#if MC_VER == MC_1_20_6
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.status.ChunkType;
#elif MC_VER == MC_1_21
#elif MC_VER >= MC_1_21_1
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.status.ChunkType;
#endif
@@ -325,7 +325,7 @@ public class ChunkLoader
}
private static
#if MC_VER < MC_1_20_6 ChunkStatus.ChunkType
#elif MC_VER < MC_1_21 ChunkType
#elif MC_VER < MC_1_21_1 ChunkType
#else ChunkType #endif
readChunkType(CompoundTag tagLevel)
{
@@ -1,6 +1,6 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
#if MC_VER >= MC_1_21
#if MC_VER >= MC_1_21_1
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.world.level.ChunkPos;
@@ -63,7 +63,7 @@ import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.status.*;
#endif
#if MC_VER == MC_1_21
#if MC_VER >= MC_1_21_1
import net.minecraft.util.StaticCache2D;
import com.google.common.collect.ImmutableList;
import net.minecraft.server.level.GenerationChunkHolder;
@@ -127,7 +127,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion
{
#if MC_VER == MC_1_16_5
super(serverLevel, chunkList);
#elif MC_VER < MC_1_21
#elif MC_VER < MC_1_21_1
super(serverLevel, chunkList, chunkStatus, writeRadius);
#else
super(serverLevel,
@@ -68,7 +68,7 @@ public final class StepBiomes
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
@@ -89,7 +89,7 @@ public final class StepBiomes
#elif MC_VER < MC_1_19_4
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
#elif MC_VER < MC_1_21
#elif MC_VER < MC_1_21_1
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
#else
@@ -66,7 +66,7 @@ public final class StepFeatures
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
@@ -68,7 +68,7 @@ public final class StepNoise
continue;
}
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
@@ -87,7 +87,7 @@ public final class StepNoise
#elif MC_VER < MC_1_19_2
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
#elif MC_VER < MC_1_21
#elif MC_VER < MC_1_21_1
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), this.environment.params.randomState,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
#else
@@ -66,7 +66,7 @@ public final class StepStructureReference
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
@@ -83,7 +83,7 @@ public final class StepStructureStart
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
@@ -65,7 +65,7 @@ public final class StepSurface
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
@@ -123,8 +123,11 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// ClientChunkLoadEvent
ClientChunkEvents.CHUNK_LOAD.register((level, chunk) ->
{
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, level, wrappedLevel), wrappedLevel);
if (MC.clientConnectedToDedicatedServer())
{
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, level, wrappedLevel), wrappedLevel);
}
});
// (kinda) block break event
@@ -206,14 +209,6 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
});
// Client Chunk Save
ClientChunkEvents.CHUNK_UNLOAD.register((level, chunk) ->
{
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
SharedApi.INSTANCE.chunkUnloadEvent(new ChunkWrapper(chunk, level, wrappedLevel), wrappedLevel);
});
//==============//
// render event //
@@ -233,14 +228,14 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
this.clientApi.renderLods(ClientLevelWrapper.getWrapper(renderContext.world()),
modelViewMatrix,
projectionMatrix,
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
renderContext.tickDelta()
#else
renderContext.tickCounter().getGameTimeDeltaTicks()
#endif
);
});
// Debug keyboard event
// FIXME: Use better hooks so it doesn't trigger key press events in text boxes
ClientTickEvents.END_CLIENT_TICK.register(client ->
@@ -116,7 +116,7 @@ public class MixinLevelRenderer
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level),
mcModelViewMatrix,
mcProjectionMatrix,
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
Minecraft.getInstance().getFrameTime()
#else
Minecraft.getInstance().getTimer().getRealtimeDeltaTicks()
@@ -45,7 +45,7 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Shadow;
#endif
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
import net.minecraft.client.gui.screens.OptionsScreen;
#else
import net.minecraft.client.gui.screens.options.OptionsScreen;
@@ -64,7 +64,7 @@ public class MixinOptionsScreen extends Screen
/** Texture used for the config opening button */
@Unique
private static final ResourceLocation ICON_TEXTURE =
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
#else
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
@@ -1,8 +1,6 @@
package com.seibel.distanthorizons.fabric.mixins.server;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
@@ -32,62 +30,6 @@ public class MixinChunkMap
// 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)
{
// true means a chunk was saved to disk
if (ci.getReturnValue())
{
// 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)
);
}
}
{ MixinChunkMapCommon.onChunkSave(this.level, chunk, ci); }
}
@@ -11,17 +11,25 @@ import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.config.Config;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
{
private final ServerLevel level;
private final IDhApiLevelWrapper levelWrapper;
//=============//
// constructor //
//=============//
public TestWorldGenerator(ServerLevel level)
{
this.level = level;
@@ -29,13 +37,23 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
}
//============//
// properties //
//============//
@Override
public EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.API_CHUNKS; }
@Override
public boolean isBusy() { return false; }
@Override
public boolean runApiChunkValidation() { return true; }
//==================//
// chunk generation //
//==================//
@Override
public Object[] generateChunk(int chunkX, int chunkZ, EDhApiDistantGeneratorMode eDhApiDistantGeneratorMode)
{
@@ -50,10 +68,10 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
// (and it is only needed when testing world gen overrides/API chunks, so it isn't normally needed)
#if MC_VER >= MC_1_18_2
ChunkAccess chunk = this.level.getChunk(chunkPosX, chunkPosZ);
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, null, null);
int minBuildHeight = chunkWrapper.getMinBuildHeight();
int maxBuildHeight = chunkWrapper.getMaxBuildHeight();
int minBuildHeight = this.level.getMinBuildHeight();
int maxBuildHeight = this.level.getMaxBuildHeight();
DhApiChunk apiChunk = DhApiChunk.create(chunkPosX, chunkPosZ, minBuildHeight, maxBuildHeight);
for (int x = 0; x < 16; x++)
@@ -84,6 +102,12 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
@Override
public void preGeneratorTaskStart() { /* do nothing */ }
//=========//
// cleanup //
//=========//
@Override
public void close() { /* do nothing */ }
@@ -5,7 +5,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IBCLibAcces
#elif MC_VER == MC_1_18_2
import ru.bclib.config.ClientConfig;
import ru.bclib.config.Configs;
#elif MC_VER < MC_1_21
#elif MC_VER < MC_1_21_1
import org.betterx.bclib.config.ClientConfig;
import org.betterx.bclib.config.Configs;
#endif
@@ -170,53 +170,59 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
@SubscribeEvent
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
if (MC.clientConnectedToDedicatedServer())
{
return;
}
//LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
#if MC_VER < MC_1_19_2
LevelAccessor level = event.getWorld();
#else
LevelAccessor level = event.getLevel();
#endif
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
return;
}
//LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
#if MC_VER < MC_1_19_2
LevelAccessor level = event.getWorld();
#else
LevelAccessor level = event.getLevel();
#endif
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
}
}
}
@SubscribeEvent
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
if (MC.clientConnectedToDedicatedServer())
{
return;
}
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
#if MC_VER < MC_1_19_2
LevelAccessor level = event.getWorld();
#else
LevelAccessor level = event.getLevel();
#endif
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
return;
}
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
#if MC_VER < MC_1_19_2
LevelAccessor level = event.getWorld();
#else
LevelAccessor level = event.getLevel();
#endif
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
}
}
}
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
@@ -224,21 +230,16 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
SharedApi.INSTANCE.chunkBlockChangedEvent(new ChunkWrapper(chunk, level, wrappedLevel), wrappedLevel);
}
@SubscribeEvent
public void clientChunkLoadEvent(ChunkEvent.Load event)
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), wrappedLevel);
SharedApi.INSTANCE.chunkLoadEvent(chunk, wrappedLevel);
}
@SubscribeEvent
public void clientChunkUnloadEvent(ChunkEvent.Unload event)
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), wrappedLevel);
SharedApi.INSTANCE.chunkUnloadEvent(chunk, wrappedLevel);
if (MC.clientConnectedToDedicatedServer())
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), wrappedLevel);
SharedApi.INSTANCE.chunkLoadEvent(chunk, wrappedLevel);
}
}
@@ -151,14 +151,6 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), levelWrapper);
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
}
@SubscribeEvent
public void serverChunkSaveEvent(ChunkEvent.Unload event)
{
ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), levelWrapper);
this.serverApi.serverChunkSaveEvent(chunk, levelWrapper);
}
@SubscribeEvent
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
@@ -0,0 +1,35 @@
package com.seibel.distanthorizons.forge.mixins.server;
import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.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;
// 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)
{ MixinChunkMapCommon.onChunkSave(this.level, chunk, ci); }
}
@@ -5,8 +5,8 @@
"mixins": [
"server.MixinUtilBackgroundThread",
"server.MixinChunkGenerator",
"server.MixinTFChunkGenerator",
"server.MixinServerPlayer"
"server.MixinTFChunkGenerator",
"server.MixinChunkMap"
],
"client": [
"client.MixinClientPacketListener",
@@ -16,7 +16,7 @@
"client.MixinLevelRenderer",
"client.MixinLightTexture",
"client.MixinOptionsScreen",
"client.MixinTextureUtil"
"client.MixinTextureUtil"
],
"server": []
}
}
+2 -2
View File
@@ -5,7 +5,7 @@ org.gradle.caching=true
# Mod Info
mod_name=DistantHorizons
mod_version=2.1.3-a-dev
mod_version=2.2.1-a-dev
api_version=3.0.0
maven_group=com.seibel.distanthorizons
mod_readable_name=Distant Horizons
@@ -48,7 +48,7 @@ versionStr=
# This defines what MC version Intellij will use for the preprocessor
# and what version is used automatically by build and run commands
mcVer=1.21
mcVer=1.21.1
# Defines the maximum amount of memory Minecraft is allowed when run in a development environment
#minecraftMemoryJavaArg="-Xmx4G"
@@ -60,6 +60,8 @@ import org.lwjgl.opengl.GL32;
import net.neoforged.neoforge.event.TickEvent;
#else
import net.neoforged.neoforge.client.event.ClientTickEvent;
import java.util.concurrent.ThreadPoolExecutor;
#endif
@@ -160,49 +162,55 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
@SubscribeEvent
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
if (MC.clientConnectedToDedicatedServer())
{
return;
}
// executor to prevent locking up the render/event thread
// if the getChunk() takes longer than expected
// (which can be caused by certain mods)
var executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
//LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
return;
}
// executor to prevent locking up the render/event thread
// if the getChunk() takes longer than expected
// (which can be caused by certain mods)
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
//LOGGER.trace("interact or block place event at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
}
}
}
@SubscribeEvent
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
{
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
if (MC.clientConnectedToDedicatedServer())
{
return;
}
// executor to prevent locking up the render/event thread
// if the getChunk() takes longer than expected
// (which can be caused by certain mods)
var executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(event.getPos().getX(), event.getPos().getZ()))
{
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
return;
}
// executor to prevent locking up the render/event thread
// if the getChunk() takes longer than expected
// (which can be caused by certain mods)
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
ChunkAccess chunk = level.getChunk(event.getPos());
this.onBlockChangeEvent(level, chunk);
});
}
}
}
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
@@ -212,22 +220,6 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
}
@SubscribeEvent
public void clientChunkLoadEvent(ChunkEvent.Load event)
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), wrappedLevel);
SharedApi.INSTANCE.chunkLoadEvent(chunk, wrappedLevel);
}
@SubscribeEvent
public void clientChunkUnloadEvent(ChunkEvent.Unload event)
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), wrappedLevel);
SharedApi.INSTANCE.chunkUnloadEvent(chunk, wrappedLevel);
}
//==============//
// key bindings //
@@ -127,14 +127,6 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), levelWrapper);
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
}
@SubscribeEvent
public void serverChunkSaveEvent(ChunkEvent.Unload event)
{
ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), levelWrapper);
this.serverApi.serverChunkSaveEvent(chunk, levelWrapper);
}
@SubscribeEvent
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
@@ -120,7 +120,7 @@ public class MixinLevelRenderer
float frameTime;
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
frameTime = Minecraft.getInstance().getFrameTime();
#else
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
@@ -45,7 +45,7 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Shadow;
#endif
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
import net.minecraft.client.gui.screens.OptionsScreen;
#else
import net.minecraft.client.gui.screens.options.OptionsScreen;
@@ -64,7 +64,7 @@ public class MixinOptionsScreen extends Screen
/** Texture used for the config opening button */
@Unique
private static final ResourceLocation ICON_TEXTURE =
#if MC_VER < MC_1_21
#if MC_VER < MC_1_21_1
new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
#else
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "textures/gui/button.png");
@@ -0,0 +1,35 @@
package com.seibel.distanthorizons.neoforge.mixins.server;
import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.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;
// 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)
{ MixinChunkMapCommon.onChunkSave(this.level, chunk, ci); }
}
@@ -5,8 +5,8 @@
"mixins": [
"server.MixinUtilBackgroundThread",
"server.MixinChunkGenerator",
"server.MixinTFChunkGenerator",
"server.MixinServerPlayer"
"server.MixinTFChunkGenerator",
"server.MixinChunkMap"
],
"client": [
"client.MixinClientPacketListener",
@@ -1,8 +1,8 @@
# 1.21 version
# 1.21.1 version
java_version=21
minecraft_version=1.21
minecraft_version=1.21.1
parchment_version=1.20.6:2024.05.01
compatible_minecraft_versions=["1.21.0"]
compatible_minecraft_versions=["1.21", "1.21.1"]
accessWidenerVersion=1_20_6
builds_for=fabric,neoforge
# forge is broken due to gradle/build script issues
@@ -41,8 +41,8 @@ fabric_api_version=0.100.1+1.21
enable_canvas=0
# (Neo)Forge loader
forge_version=50.0.19
neoforge_version=21.0.4-beta
forge_version=
neoforge_version=21.1.6
# (Neo)Forge mod versions
starlight_version_forge=
terraforged_version=