diff --git a/gradle.properties b/gradle.properties index 2935ecf..6216437 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G # Mod Properties - mod_version = 0.6.1 + mod_version = 0.6.6 maven_group = com.github.zly2006 archives_base_name = carpet-sls-addition diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java b/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java index c263de6..8129e3e 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java @@ -2,6 +2,7 @@ package com.github.zly2006.carpetslsaddition; import carpet.api.settings.Rule; import carpet.api.settings.RuleCategory; +import net.minecraft.block.RedstoneBlock; import static com.github.zly2006.carpetslsaddition.ServerMain.CARPET_ID; @@ -58,6 +59,12 @@ public class SLSCarpetSettings { @Rule(categories = {CARPET_ID, PCA, RuleCategory.FEATURE}) public static boolean playerSit = false; + @Rule(categories = {CARPET_ID, RuleCategory.CREATIVE}) + public static boolean oldRedstoneConnectionLogic = false; + + @Rule(categories = {CARPET_ID, RuleCategory.OPTIMIZATION}) + public static boolean optimizedOnDragonRespawn = false; + public enum PCA_SYNC_PLAYER_ENTITY_OPTIONS { NOBODY, BOT, OPS, OPS_AND_SELF, EVERYONE diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java index 91c8ff7..c0d7747 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java @@ -6,6 +6,7 @@ import com.github.zly2006.carpetslsaddition.command.BotCommand; import com.github.zly2006.carpetslsaddition.command.HatCommand; import com.github.zly2006.carpetslsaddition.command.SitCommand; import com.github.zly2006.carpetslsaddition.network.pca.PcaSyncProtocol; +import com.github.zly2006.carpetslsaddition.util.access.SettingsManagerAccessor; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/block/RewriteChainRestrictedNeighborUpdater.java b/src/main/java/com/github/zly2006/carpetslsaddition/block/RewriteChainRestrictedNeighborUpdater.java new file mode 100644 index 0000000..ea95264 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/block/RewriteChainRestrictedNeighborUpdater.java @@ -0,0 +1,180 @@ +package com.github.zly2006.carpetslsaddition.block; + +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import com.mojang.logging.LogUtils; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import net.minecraft.world.block.NeighborUpdater; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; + +public class RewriteChainRestrictedNeighborUpdater implements NeighborUpdater { + private static final Logger LOGGER = LogUtils.getLogger(); + private final World world; + private final int maxChainDepth; + private final ArrayDeque queue = new ArrayDeque<>(); + private final List pending = new ArrayList<>(); + private int depth = 0; + + // rewrite part + private boolean needUpdate = true; + + + public RewriteChainRestrictedNeighborUpdater(World world, int maxChainDepth) { + this.world = world; + this.maxChainDepth = maxChainDepth; + } + + public void replaceWithStateForNeighborUpdate(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int flags, int maxUpdateDepth) { + this.enqueue(pos, new StateReplacementEntry(direction, neighborState, pos.toImmutable(), neighborPos.toImmutable(), flags, maxUpdateDepth)); + } + + public void updateNeighbor(BlockPos pos, Block sourceBlock, BlockPos sourcePos) { + this.enqueue(pos, new SimpleEntry(pos, sourceBlock, sourcePos.toImmutable())); + } + + public void updateNeighbor(BlockState state, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { + this.enqueue(pos, new StatefulEntry(state, pos.toImmutable(), sourceBlock, sourcePos.toImmutable(), notify)); + } + + public void updateNeighbors(BlockPos pos, Block sourceBlock, @Nullable Direction except) { + this.enqueue(pos, new SixWayEntry(pos.toImmutable(), sourceBlock, except)); + } + + private void enqueue(BlockPos pos, Entry entry) { + int maxSize = SLSCarpetSettings.maxUpdateQueueSize; + if (maxSize > 0) { + needUpdate = this.pending.size() + 1 <= maxSize; + } + else { + needUpdate = true; + } + + boolean notEmpty = this.depth > 0; + boolean isFull = this.maxChainDepth >= 0 && this.depth >= this.maxChainDepth; + ++this.depth; + if (!isFull) { + if (notEmpty) { + this.pending.add(entry); + } else { + this.queue.push(entry); + } + } + else if (this.depth - 1 == this.maxChainDepth) { + LOGGER.error("Too many chained neighbor updates. Skipping the rest. First skipped position: " + pos.toShortString()); + } + + if (!notEmpty) { + this.runQueuedUpdates(); + } + + } + + private void runQueuedUpdates() { + try { + while(!this.queue.isEmpty() || !this.pending.isEmpty()) { + if (SLSCarpetSettings.maxUpdateQueueSize == 0) { + break; + } + + for(int i = this.pending.size() - 1; i >= 0; --i) { + this.queue.push(this.pending.get(i)); + } + + this.pending.clear(); + Entry entry = this.queue.peek(); + assert entry != null; + + if (needUpdate) { + while(this.pending.isEmpty()) { + if (!entry.update(this.world)) { + this.queue.pop(); + break; + } + } + } + else { + entry.update(this.world); + throw new OutOfMemoryError("Create by Carpet-SLS-Addition"); + } + } + } + catch (OutOfMemoryError e) { + if (e.getMessage().endsWith("Carpet-SLS-Addition")) { + LOGGER.error("The update queue exceeded the maximum allowed allocation of heap space set by SLS Addition!", e); + } + else { + throw e; + } + } + finally { + this.queue.clear(); + this.pending.clear(); + this.depth = 0; + } + } + + + private interface Entry { + boolean update(World world); + } + + private record StateReplacementEntry(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int updateFlags, int updateLimit) implements Entry { + + public boolean update(World world) { + NeighborUpdater.replaceWithStateForNeighborUpdate(world, this.direction, this.neighborState, this.pos, this.neighborPos, this.updateFlags, this.updateLimit); + return false; + } + } + + record SimpleEntry(BlockPos pos, Block sourceBlock, BlockPos sourcePos) implements Entry { + public boolean update(World world) { + BlockState blockState = world.getBlockState(this.pos); + NeighborUpdater.tryNeighborUpdate(world, blockState, this.pos, this.sourceBlock, this.sourcePos, false); + return false; + } + } + + record StatefulEntry(BlockState state, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean movedByPiston) implements Entry { + public boolean update(World world) { + NeighborUpdater.tryNeighborUpdate(world, this.state, this.pos, this.sourceBlock, this.sourcePos, this.movedByPiston); + return false; + } + } + + static final class SixWayEntry implements Entry { + private final BlockPos pos; + private final Block sourceBlock; + @Nullable + private final Direction except; + private int currentDirectionIndex = 0; + + SixWayEntry(BlockPos pos, Block sourceBlock, @Nullable Direction except) { + this.pos = pos; + this.sourceBlock = sourceBlock; + this.except = except; + if (NeighborUpdater.UPDATE_ORDER[this.currentDirectionIndex] == except) { + ++this.currentDirectionIndex; + } + + } + + public boolean update(World world) { + BlockPos blockPos = this.pos.offset(NeighborUpdater.UPDATE_ORDER[this.currentDirectionIndex++]); + BlockState blockState = world.getBlockState(blockPos); + blockState.neighborUpdate(world, blockPos, this.sourceBlock, this.pos, false); + if (this.currentDirectionIndex < NeighborUpdater.UPDATE_ORDER.length && NeighborUpdater.UPDATE_ORDER[this.currentDirectionIndex] == this.except) { + ++this.currentDirectionIndex; + } + + return this.currentDirectionIndex < NeighborUpdater.UPDATE_ORDER.length; + } + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/command/BotCommand.java b/src/main/java/com/github/zly2006/carpetslsaddition/command/BotCommand.java index 58587a4..bc31773 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/command/BotCommand.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/command/BotCommand.java @@ -5,7 +5,7 @@ import carpet.fakes.ServerPlayerInterface; import carpet.helpers.EntityPlayerActionPack; import carpet.patches.EntityPlayerMPFake; import carpet.utils.Messenger; -import com.github.zly2006.carpetslsaddition.PlayerAccess; +import com.github.zly2006.carpetslsaddition.util.access.PlayerAccess; import com.github.zly2006.carpetslsaddition.ServerMain; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.Command; diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/BlockPatternTestTransformInvoker.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/BlockPatternTestTransformInvoker.java new file mode 100644 index 0000000..a0249fb --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/BlockPatternTestTransformInvoker.java @@ -0,0 +1,15 @@ +package com.github.zly2006.carpetslsaddition.mixin.block; + +import com.google.common.cache.LoadingCache; +import net.minecraft.block.pattern.BlockPattern; +import net.minecraft.block.pattern.CachedBlockPosition; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(BlockPattern.class) +public interface BlockPatternTestTransformInvoker { + @Invoker("testTransform") + BlockPattern.Result invokeTestTransform(BlockPos frontTopLeft, Direction forwards, Direction up, LoadingCache cache); +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinBlock.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinBlock.java index a1fcf52..fad38c4 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinBlock.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinBlock.java @@ -1,6 +1,6 @@ package com.github.zly2006.carpetslsaddition.mixin.block; -import com.github.zly2006.carpetslsaddition.PlayerAccess; +import com.github.zly2006.carpetslsaddition.util.access.PlayerAccess; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinRedstoneWireBlock.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinRedstoneWireBlock.java new file mode 100644 index 0000000..136959c --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinRedstoneWireBlock.java @@ -0,0 +1,23 @@ +package com.github.zly2006.carpetslsaddition.mixin.block; + +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.RedstoneWireBlock; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(value = RedstoneWireBlock.class, priority = 1) +public class MixinRedstoneWireBlock { + @Redirect(method = "getRenderConnectionType(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/Direction;Z)Lnet/minecraft/block/enums/WireConnection;", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getBlock()Lnet/minecraft/block/Block;")) + public Block redirectConnectionBlockState(BlockState instance) { + if (SLSCarpetSettings.oldRedstoneConnectionLogic) { + return Blocks.AIR; + } + else { + return instance.getBlock(); + } + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/carpet/MixinSettingsManager.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/carpet/MixinSettingsManager.java index b4d541b..08934c3 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/carpet/MixinSettingsManager.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/carpet/MixinSettingsManager.java @@ -1,9 +1,19 @@ package com.github.zly2006.carpetslsaddition.mixin.carpet; +import carpet.api.settings.CarpetRule; import carpet.api.settings.SettingsManager; -import com.github.zly2006.carpetslsaddition.SettingsManagerAccessor; +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import com.github.zly2006.carpetslsaddition.ServerMain; +import com.github.zly2006.carpetslsaddition.util.NeighborUpdaterChanger; +import com.github.zly2006.carpetslsaddition.util.access.SettingsManagerAccessor; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.world.ServerWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(value = SettingsManager.class, remap = false) public abstract class MixinSettingsManager implements SettingsManagerAccessor { @@ -13,4 +23,21 @@ public abstract class MixinSettingsManager implements SettingsManagerAccessor { public void loadSettings() { this.loadConfigurationFromConf(); } + + @Inject(method = "setRule", at = @At(value = "INVOKE", target = "Lcarpet/utils/Messenger;m(Lnet/minecraft/server/command/ServerCommandSource;[Ljava/lang/Object;)V", shift = At.Shift.BEFORE)) + private void injectSetRule(ServerCommandSource source, CarpetRule rule, String newValue, CallbackInfoReturnable cir) { + if ("maxUpdateQueueSize".equals(rule.name())) { + MinecraftServer server = ServerMain.server; + + if (server != null) + { + server.execute(() -> { + for (ServerWorld world : server.getWorlds()) + { + ((NeighborUpdaterChanger)world).useRewriteChainNeighborUpdater(SLSCarpetSettings.maxUpdateQueueSize > -1); + } + }); + } + } + } } diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinEnderDragonFight.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinEnderDragonFight.java new file mode 100644 index 0000000..9da4dc7 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinEnderDragonFight.java @@ -0,0 +1,133 @@ +package com.github.zly2006.carpetslsaddition.mixin.entity; + +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import com.github.zly2006.carpetslsaddition.mixin.block.BlockPatternTestTransformInvoker; +import com.google.common.cache.LoadingCache; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.EndGatewayBlockEntity; +import net.minecraft.block.entity.EndPortalBlockEntity; +import net.minecraft.block.pattern.BlockPattern; +import net.minecraft.block.pattern.CachedBlockPosition; +import net.minecraft.entity.boss.dragon.EnderDragonFight; +import net.minecraft.entity.decoration.EndCrystalEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.Heightmap; +import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.gen.feature.EndPortalFeature; +import net.minecraft.world.WorldView; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(EnderDragonFight.class) +public class MixinEnderDragonFight { + @Shadow + @Final + private ServerWorld world; + + @Shadow + @Final + private BlockPattern endPortalPattern; + + @Shadow + private BlockPos exitPortalLocation; + @Shadow + private boolean doLegacyCheck; + + @Unique + private int defaultChunkX = -8; + @Unique + private int defaultChunkZ = -8; + @Unique + private int defaultOriginY = -1; + + /** + * @author Disy920 + * @reason Optimize the search process of the end portal + */ + @Overwrite + private @Nullable BlockPattern.Result findEndPortal() { + int i,j; + if(!SLSCarpetSettings.optimizedOnDragonRespawn) { + defaultChunkX = -8; + defaultChunkZ = -8; + } + for(i = defaultChunkX; i <= 8; ++i) { + for(j = defaultChunkZ; j <= 8; ++j) { + WorldChunk worldChunk = this.world.getChunk(i, j); + for(BlockEntity blockEntity : worldChunk.getBlockEntities().values()) { + if(SLSCarpetSettings.optimizedOnDragonRespawn && blockEntity instanceof EndGatewayBlockEntity) continue; + if (blockEntity instanceof EndPortalBlockEntity) { + BlockPattern.Result result = this.endPortalPattern.searchAround(this.world, blockEntity.getPos()); + if (result != null) { + BlockPos blockPos = result.translate(3, 3, 3).getBlockPos(); + if (this.exitPortalLocation == null) { + this.exitPortalLocation = blockPos; + } + defaultChunkX = i; + defaultChunkZ = j; + return result; + } + } + } + } + } + if(this.doLegacyCheck || this.exitPortalLocation == null){ + if(SLSCarpetSettings.optimizedOnDragonRespawn && defaultOriginY != -1) { + i = defaultOriginY; + } + else { + i = this.world.getTopPosition(Heightmap.Type.MOTION_BLOCKING, EndPortalFeature.offsetOrigin(BlockPos.ORIGIN)).getY(); + } + boolean notFirstSearch = false; + for(j = i; j >= 0; --j) { + BlockPattern.Result result2; + if(SLSCarpetSettings.optimizedOnDragonRespawn && notFirstSearch) { + result2 = partialSearchAround(this.endPortalPattern, this.world, new BlockPos(EndPortalFeature.offsetOrigin(BlockPos.ORIGIN).getX(), j, EndPortalFeature.offsetOrigin(BlockPos.ORIGIN).getZ())); + } + else{ + result2 = this.endPortalPattern.searchAround(this.world, new BlockPos(EndPortalFeature.offsetOrigin(BlockPos.ORIGIN).getX(), j, EndPortalFeature.offsetOrigin(BlockPos.ORIGIN).getZ())); + } + if (result2 != null) { + if (this.exitPortalLocation == null) { + this.exitPortalLocation = result2.translate(3, 3, 3).getBlockPos(); + } + defaultOriginY = j; + return result2; + } + notFirstSearch = true; + } + } + + return null; + } + + @Inject(method = "respawnDragon(Ljava/util/List;)V", at = @At("HEAD")) + private void resetCache(List crystals, CallbackInfo ci) { + this.defaultChunkX = -8; + this.defaultChunkZ = -8; + this.defaultOriginY = -1; + } + + @Unique + private BlockPattern.Result partialSearchAround(BlockPattern pattern, WorldView world, BlockPos pos) { + LoadingCache loadingCache = BlockPattern.makeCache(world, false); + int i = Math.max(Math.max(pattern.getWidth(), pattern.getHeight()), pattern.getDepth()); + for (BlockPos blockPos : BlockPos.iterate(pos, pos.add(i - 1, 0, i - 1))) { + for (Direction direction : Direction.values()) { + for (Direction direction2 : Direction.values()) { + BlockPattern.Result result; + if (direction2 == direction || direction2 == direction.getOpposite() || (result = ((BlockPatternTestTransformInvoker)pattern).invokeTestTransform(blockPos, direction, direction2, loadingCache)) == null) continue; + return result; + } + } + } + return null; + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinPlayerEntity.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinPlayerEntity.java index e50b235..32a47ee 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinPlayerEntity.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/entity/MixinPlayerEntity.java @@ -1,6 +1,6 @@ package com.github.zly2006.carpetslsaddition.mixin.entity; -import com.github.zly2006.carpetslsaddition.PlayerAccess; +import com.github.zly2006.carpetslsaddition.util.access.PlayerAccess; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.EquipmentSlot; diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/item/MixinItem.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/item/MixinItem.java index 37972c0..4fe1275 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/item/MixinItem.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/item/MixinItem.java @@ -1,6 +1,6 @@ package com.github.zly2006.carpetslsaddition.mixin.item; -import com.github.zly2006.carpetslsaddition.PlayerAccess; +import com.github.zly2006.carpetslsaddition.util.access.PlayerAccess; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.player.PlayerEntity; diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/server/MixinMinecraftDedicatedServer.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/server/MixinMinecraftDedicatedServer.java new file mode 100644 index 0000000..d8f8882 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/server/MixinMinecraftDedicatedServer.java @@ -0,0 +1,24 @@ +package com.github.zly2006.carpetslsaddition.mixin.server; + +import com.github.zly2006.carpetslsaddition.util.access.ServerAccess; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.server.dedicated.MinecraftDedicatedServer; +import net.minecraft.server.dedicated.ServerPropertiesLoader; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Environment(EnvType.SERVER) +@Mixin(MinecraftDedicatedServer.class) +public class MixinMinecraftDedicatedServer implements ServerAccess { + + @Shadow + @Final + private ServerPropertiesLoader propertiesLoader; + + @Override + public ServerPropertiesLoader getPropertiesLoader() { + return propertiesLoader; + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/world/MixinChainRestrictedNeighborUpdater.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/world/MixinChainRestrictedNeighborUpdater.java deleted file mode 100644 index 4c14094..0000000 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/world/MixinChainRestrictedNeighborUpdater.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.github.zly2006.carpetslsaddition.mixin.world; - -import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.block.ChainRestrictedNeighborUpdater; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.ArrayDeque; -import java.util.List; - -@Mixin(ChainRestrictedNeighborUpdater.class) -public class MixinChainRestrictedNeighborUpdater { - - @Shadow - @Final - private ArrayDeque queue; - - @Shadow - @Final - private List pending; - - @Shadow - private int depth; - - @Inject(method = "enqueue", at = @At(value = "INVOKE", target = "Ljava/util/ArrayDeque;push(Ljava/lang/Object;)V"), cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT) - public void injectEnqueue(BlockPos pos, ChainRestrictedNeighborUpdater.Entry entry, CallbackInfo ci, boolean bl) { - int maxSize = SLSCarpetSettings.maxUpdateQueueSize; - if (maxSize > 0) { - if (this.depth + 1 > maxSize) { - this.queue.clear(); - this.pending.clear(); - this.depth = 0; - bl = true; - Throwable e = new OutOfMemoryError("Create by Carpet-SLS-Addition: The update queue exceeded the maximum allowed allocation of heap space set by SLS Addition!"); - e.printStackTrace(); - ci.cancel(); - } - } - } -} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/world/MixinWorld.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/world/MixinWorld.java new file mode 100644 index 0000000..9db936c --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/world/MixinWorld.java @@ -0,0 +1,43 @@ +package com.github.zly2006.carpetslsaddition.mixin.world; + +import com.github.zly2006.carpetslsaddition.ServerMain; +import com.github.zly2006.carpetslsaddition.block.RewriteChainRestrictedNeighborUpdater; +import com.github.zly2006.carpetslsaddition.util.NeighborUpdaterChanger; +import com.github.zly2006.carpetslsaddition.util.access.ServerAccess; +import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.world.World; +import net.minecraft.world.block.NeighborUpdater; +import org.spongepowered.asm.mixin.*; + +@Mixin(World.class) +public abstract class MixinWorld implements NeighborUpdaterChanger { + @Mutable + @Shadow + @Final + protected NeighborUpdater neighborUpdater; + + @Unique + private NeighborUpdater previousUpdater = null; + + @Override + public void useRewriteChainNeighborUpdater(boolean use) { + if (use) { + this.previousUpdater = this.neighborUpdater; + int maxDepth; + + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) { + maxDepth = ((ServerAccess) ServerMain.server).getPropertiesLoader().getPropertiesHandler().maxChainedNeighborUpdates; + } + else { + maxDepth = 1000000; + } + + this.neighborUpdater = new RewriteChainRestrictedNeighborUpdater((World)(Object)this, maxDepth); + + } + else { + this.neighborUpdater = previousUpdater; + } + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/util/NeighborUpdaterChanger.java b/src/main/java/com/github/zly2006/carpetslsaddition/util/NeighborUpdaterChanger.java new file mode 100644 index 0000000..146a57c --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/util/NeighborUpdaterChanger.java @@ -0,0 +1,7 @@ +package com.github.zly2006.carpetslsaddition.util; + +import net.minecraft.world.block.NeighborUpdater; + +public interface NeighborUpdaterChanger { + void useRewriteChainNeighborUpdater(boolean use); +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/PlayerAccess.java b/src/main/java/com/github/zly2006/carpetslsaddition/util/access/PlayerAccess.java similarity index 71% rename from src/main/java/com/github/zly2006/carpetslsaddition/PlayerAccess.java rename to src/main/java/com/github/zly2006/carpetslsaddition/util/access/PlayerAccess.java index cc5ec96..3021139 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/PlayerAccess.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/util/access/PlayerAccess.java @@ -1,4 +1,4 @@ -package com.github.zly2006.carpetslsaddition; +package com.github.zly2006.carpetslsaddition.util.access; import net.minecraft.text.Text; diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/util/access/ServerAccess.java b/src/main/java/com/github/zly2006/carpetslsaddition/util/access/ServerAccess.java new file mode 100644 index 0000000..7adab11 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/util/access/ServerAccess.java @@ -0,0 +1,7 @@ +package com.github.zly2006.carpetslsaddition.util.access; + +import net.minecraft.server.dedicated.ServerPropertiesLoader; + +public interface ServerAccess { + ServerPropertiesLoader getPropertiesLoader(); +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/SettingsManagerAccessor.java b/src/main/java/com/github/zly2006/carpetslsaddition/util/access/SettingsManagerAccessor.java similarity index 55% rename from src/main/java/com/github/zly2006/carpetslsaddition/SettingsManagerAccessor.java rename to src/main/java/com/github/zly2006/carpetslsaddition/util/access/SettingsManagerAccessor.java index 6cf21b0..cc843ab 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/SettingsManagerAccessor.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/util/access/SettingsManagerAccessor.java @@ -1,4 +1,4 @@ -package com.github.zly2006.carpetslsaddition; +package com.github.zly2006.carpetslsaddition.util.access; public interface SettingsManagerAccessor { void loadSettings(); diff --git a/src/main/resources/assets/slsaddition/lang/en_us.json b/src/main/resources/assets/slsaddition/lang/en_us.json index 398a8ec..131e155 100644 --- a/src/main/resources/assets/slsaddition/lang/en_us.json +++ b/src/main/resources/assets/slsaddition/lang/en_us.json @@ -20,7 +20,9 @@ "carpet.rule.canUseHatCommand.name": "Enable hat command", "carpet.rule.canUseSitCommand.name": "Enable sit command", "carpet.rule.maxUpdateQueueSize.name": "Maximum allowed capacity of update queue", - + "carpet.rule.oldRedstoneConnectionLogic.name": "Restore the previous redstone wire connection logic", + "carpet.rule.optimizedOnDragonRespawn.name": "Optimize the dragon respawn", + "carpet.rule.obtainableReinforcedDeepSlate.desc": "When an anvil falls on 64 dropped deepslates, they will be turned in a reinforced deepslate instead of disappearing.", "carpet.rule.skipTicksForJoblessVillager.desc": "For jobless/nitwit villagers, after performing a set number of tick operations, skip the 1 tick operation.", "carpet.rule.maxVillagersInABlock.desc": "The maximum number of villagers that can be in a block, set to -1 to disable.", @@ -37,6 +39,8 @@ "carpet.rule.canUseHatCommand.desc": "Allows all players to use the /hat command to place their main hand items in the helmet slot", "carpet.rule.canUseSitCommand.desc": "Allows all players to use the /sit command to sit down", "carpet.rule.maxUpdateQueueSize.desc": "Set the maximum allowed length of the update queue", + "carpet.rule.oldRedstoneConnectionLogic.desc": "Restore the interaction logic between the Redstone wire and the trap door to the performance of versions 1.19 and earlier", + "carpet.rule.optimizedOnDragonRespawn.desc": "Optimize the dragon respawn process", "carpet.rule.autoUrl.extra.0": "The URL sent by players to be directly clicked and redirected by other players", "carpet.rule.skipTicksForJoblessVillager.extra.0": "Set to 0 to maintain the vanilla behavior", diff --git a/src/main/resources/assets/slsaddition/lang/zh_cn.json b/src/main/resources/assets/slsaddition/lang/zh_cn.json index 1114f3f..4f03195 100644 --- a/src/main/resources/assets/slsaddition/lang/zh_cn.json +++ b/src/main/resources/assets/slsaddition/lang/zh_cn.json @@ -20,6 +20,8 @@ "carpet.rule.canUseHatCommand.name": "启用戴帽指令", "carpet.rule.canUseSitCommand.name": "启用坐下指令", "carpet.rule.maxUpdateQueueSize.name": "最大更新队列容量", + "carpet.rule.oldRedstoneConnectionLogic.name": "恢复红石线连接逻辑", + "carpet.rule.optimizedOnDragonRespawn.name": "龙战优化", "carpet.rule.maxVillagersInABlock.desc": "每个方块中最大村民数量,设置-1为无限制", "carpet.rule.obtainableReinforcedDeepSlate.desc": "当铁砧在64个深板岩的掉落物上时,可以获得强化深板岩", @@ -37,6 +39,8 @@ "carpet.rule.canUseHatCommand.desc": "可让所有玩家使用/hat指令,将手中的物品置于头盔位", "carpet.rule.canUseSitCommand.desc": "可让所有玩家使用/sit指令,以在原地坐下", "carpet.rule.maxUpdateQueueSize.desc": "设定最大允许的更新队列长度", + "carpet.rule.oldRedstoneConnectionLogic.desc": "使活板门上的红石线与其他红石线连接的逻辑恢复到1.19及之前版本的表现", + "carpet.rule.optimizedOnDragonRespawn.desc": "对重生末影龙的过程进行优化", "carpet.rule.autoUrl.extra.0": "使玩家发出的URL可以被其他玩家直接点击跳转", "carpet.rule.skipTicksForJoblessVillager.extra.0": "设置为0则保持原版行为", diff --git a/src/main/resources/slsaddition.mixins.json b/src/main/resources/slsaddition.mixins.json index 9762a92..f861a9d 100644 --- a/src/main/resources/slsaddition.mixins.json +++ b/src/main/resources/slsaddition.mixins.json @@ -4,14 +4,18 @@ "package": "com.github.zly2006.carpetslsaddition.mixin", "compatibilityLevel": "JAVA_17", "server": [ + "server.MixinMinecraftDedicatedServer" ], "client": [ ], "mixins": [ + "block.BlockPatternTestTransformInvoker", "block.MixinBlock", + "block.MixinRedstoneWireBlock", "carpet.MixinFakePlayer", "carpet.MixinSettingsManager", "entity.MixinArmorStandEntity", + "entity.MixinEnderDragonFight", "entity.MixinFallingBlockEntity", "entity.MixinItemEntity", "entity.MixinPlayerEntity", @@ -38,8 +42,8 @@ "screen.MixinSlot", "server.MixinMinecraftServer", "server.MixinPlayerManager", - "world.MixinChainRestrictedNeighborUpdater", - "world.MixinSpawnHelper" + "world.MixinSpawnHelper", + "world.MixinWorld" ], "injectors": { "defaultRequire": 1