From 4382448e0859bb9025c61c564a919bc40c105f8c Mon Sep 17 00:00:00 2001 From: QPCrummer <66036033+QPCrummer@users.noreply.github.com> Date: Tue, 25 Jun 2024 01:53:32 -0400 Subject: [PATCH] Additional optimizations from Leaves - Fixed c2me compatibility - Improvements to random - Improvements to JRC removal - Added a player interaction limiter - Improved AI ticking --- gradle.properties | 2 +- .../pathfinding/TargetPredicateMixin.java | 34 +++ .../LimiterBlockItemMixin.java | 33 +++ .../LimiterServerInteractionManagerMixin.java | 38 +++ .../LimiterServerPlayerEntityMixin.java | 47 ++++ .../mixin/logic/shape/VoxelShapesMixin.java | 2 +- .../CacheBlockBreakPacketMixin.java | 2 +- .../world/RandomServerChunkManagerMixin.java | 21 ++ .../random/world/RandomServerWorldMixin.java | 45 ++++ .../random/world/RandomWorldChunkMixin.java | 50 ++++ .../mixin/random/world/RandomWorldMixin.java | 26 +- .../remove/profiler/JFRCommandMixin.java | 30 --- .../mixin/remove/profiler/JFRMixin.java | 128 ---------- .../remove/profiler/ProfilerSystemMixin.java | 133 ---------- .../InteractionLimiterInterface.java | 9 + .../utils/interfaces/LightningInterface.java | 7 + .../utils/interfaces/SnowInterface.java | 5 + .../utils/random/NotThreadSafeRandomImpl.java | 120 --------- .../utils/random/XorShiftRandomImpl.java | 227 ++++++++++++++++++ ...atoptimize-mixin-config-default.properties | 1 + src/main/resources/potatoptimize.mixins.json | 20 +- 21 files changed, 553 insertions(+), 427 deletions(-) create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/entity/pathfinding/TargetPredicateMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterBlockItemMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerInteractionManagerMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerPlayerEntityMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerChunkManagerMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerWorldMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldChunkMixin.java delete mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRCommandMixin.java delete mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRMixin.java delete mode 100644 src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/ProfilerSystemMixin.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/InteractionLimiterInterface.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/LightningInterface.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/SnowInterface.java delete mode 100644 src/main/java/com/github/tatercertified/potatoptimize/utils/random/NotThreadSafeRandomImpl.java create mode 100644 src/main/java/com/github/tatercertified/potatoptimize/utils/random/XorShiftRandomImpl.java diff --git a/gradle.properties b/gradle.properties index 9b5f254..41a2cb0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.15.11 # Mod Properties - mod_version = 0.0.1-dev.1 + mod_version = 0.0.1-dev.2 maven_group = com.github.tatercertified archives_base_name = potatoptimize diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/entity/pathfinding/TargetPredicateMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/entity/pathfinding/TargetPredicateMixin.java new file mode 100644 index 0000000..8ddfa6f --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/entity/pathfinding/TargetPredicateMixin.java @@ -0,0 +1,34 @@ +package com.github.tatercertified.potatoptimize.mixin.entity.pathfinding; + +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalDoubleRef; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.TargetPredicate; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * Credit: Leaves patch #0026 + */ +@Mixin(TargetPredicate.class) +public class TargetPredicateMixin { + @Shadow private double baseMaxDistance; + + @Inject(method = "test", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getAttackDistanceScalingFactor(Lnet/minecraft/entity/Entity;)D", shift = At.Shift.BEFORE), cancellable = true) + private void quickCancelPathFinding(LivingEntity baseEntity, LivingEntity targetEntity, CallbackInfoReturnable cir, @Share("dist")LocalDoubleRef doubleRef) { + double f = baseEntity.squaredDistanceTo(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + doubleRef.set(f); + if (f > this.baseMaxDistance * this.baseMaxDistance) { + cir.setReturnValue(false); + } + } + + @Redirect(method = "test", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;squaredDistanceTo(DDD)D")) + private double borrowValueFromOtherMixin(LivingEntity instance, double x, double y, double z, @Share("dist")LocalDoubleRef doubleRef) { + return doubleRef.get(); + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterBlockItemMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterBlockItemMixin.java new file mode 100644 index 0000000..8f5f50a --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterBlockItemMixin.java @@ -0,0 +1,33 @@ +package com.github.tatercertified.potatoptimize.mixin.feature.interaction_limiter; + +import com.github.tatercertified.potatoptimize.utils.interfaces.InteractionLimiterInterface; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.ActionResult; +import org.jetbrains.annotations.Nullable; +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; + +@Environment(EnvType.SERVER) +@Mixin(BlockItem.class) +public abstract class LimiterBlockItemMixin { + @Shadow protected abstract @Nullable BlockState getPlacementState(ItemPlacementContext context); + + @Inject(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;getPlacementState(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/block/BlockState;", shift = At.Shift.AFTER), cancellable = true) + private void injectLimiter(ItemPlacementContext context, CallbackInfoReturnable cir) { + ServerPlayerEntity player = (ServerPlayerEntity) context.getPlayer(); + if (player != null && this.getPlacementState(context) != null) { + ((InteractionLimiterInterface)player).addPlaceBlockCountPerTick(); + if (!((InteractionLimiterInterface)player).allowOperation()) { + cir.setReturnValue(ActionResult.FAIL); + } + } + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerInteractionManagerMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerInteractionManagerMixin.java new file mode 100644 index 0000000..d39d480 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerInteractionManagerMixin.java @@ -0,0 +1,38 @@ +package com.github.tatercertified.potatoptimize.mixin.feature.interaction_limiter; + +import com.github.tatercertified.potatoptimize.utils.interfaces.InteractionLimiterInterface; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +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; + +@Environment(EnvType.SERVER) +@Mixin(ServerPlayerInteractionManager.class) +public abstract class LimiterServerInteractionManagerMixin { + @Shadow @Final protected ServerPlayerEntity player; + + @Shadow protected ServerWorld world; + + @Shadow protected abstract void onBlockBreakingAction(BlockPos pos, boolean success, int sequence, String reason); + + @Inject(method = "finishMining", at = @At("HEAD"), cancellable = true) + private void countBlockBreaking(BlockPos pos, int sequence, String reason, CallbackInfo ci) { + if (reason.equals("insta mine")) { + ((InteractionLimiterInterface)player).addInstaBreakCountPerTick(); + if (!((InteractionLimiterInterface)player).allowOperation()) { + this.player.networkHandler.sendPacket(new BlockUpdateS2CPacket(pos, this.world.getBlockState(pos))); + this.onBlockBreakingAction(pos, false, sequence, reason); + ci.cancel(); + } + } + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerPlayerEntityMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerPlayerEntityMixin.java new file mode 100644 index 0000000..77a5185 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/feature/interaction_limiter/LimiterServerPlayerEntityMixin.java @@ -0,0 +1,47 @@ +package com.github.tatercertified.potatoptimize.mixin.feature.interaction_limiter; + +import com.github.tatercertified.potatoptimize.utils.interfaces.InteractionLimiterInterface; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.server.network.ServerPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Environment(EnvType.SERVER) +@Mixin(ServerPlayerEntity.class) +public class LimiterServerPlayerEntityMixin implements InteractionLimiterInterface { + private int instaBreakCountPerTick = 0; + private int placeBlockCountPerTick = 0; + + private void resetOperationCountPerTick() { + instaBreakCountPerTick = 0; + placeBlockCountPerTick = 0; + } + + public int getInstaBreakCountPerTick() { + return instaBreakCountPerTick; + } + + public int getPlaceBlockCountPerTick() { + return placeBlockCountPerTick; + } + + public void addInstaBreakCountPerTick() { + ++instaBreakCountPerTick; + } + + public void addPlaceBlockCountPerTick() { + ++placeBlockCountPerTick; + } + + public boolean allowOperation() { + return (instaBreakCountPerTick == 0 || placeBlockCountPerTick == 0) && (instaBreakCountPerTick <= 1 && placeBlockCountPerTick <= 2); + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/SculkShriekerWarningManager;tick()V")) + private void injectResetOperationCounts(CallbackInfo ci) { + this.resetOperationCountPerTick(); + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/logic/shape/VoxelShapesMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/logic/shape/VoxelShapesMixin.java index 686a6b9..8077630 100644 --- a/src/main/java/com/github/tatercertified/potatoptimize/mixin/logic/shape/VoxelShapesMixin.java +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/logic/shape/VoxelShapesMixin.java @@ -38,7 +38,7 @@ private static PairList redirectListPair2(int size, DoubleList first, DoubleList } @Inject(method = "createListPair", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/doubles/DoubleList;getDouble(I)D", ordinal = 0, shift = At.Shift.BEFORE), cancellable = true) - private static void injectCreatePairList(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond, CallbackInfoReturnable cir, @Local(ordinal = 0) int i, @Local(ordinal = 0) int j) { + private static void injectCreatePairList(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond, CallbackInfoReturnable cir, @Local(ordinal = 0, argsOnly = true) int i, @Local(ordinal = 0, argsOnly = true) int j) { if (i == j && Objects.equals(first, second)) { if (first instanceof IdentityPairList) { cir.setReturnValue((PairList) first); diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/networking/block_breaking/CacheBlockBreakPacketMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/networking/block_breaking/CacheBlockBreakPacketMixin.java index a99841d..901eb31 100644 --- a/src/main/java/com/github/tatercertified/potatoptimize/mixin/networking/block_breaking/CacheBlockBreakPacketMixin.java +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/networking/block_breaking/CacheBlockBreakPacketMixin.java @@ -26,7 +26,7 @@ private void setPacketNull(int entityId, BlockPos pos, int progress, CallbackInf } @Redirect(method = "setBlockBreakingInfo", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V")) - private void redirectPacketSent(ServerPlayNetworkHandler instance, Packet packetBad, @Local(ordinal = 0) int entityId, @Local(ordinal = 0) BlockPos pos, @Local(ordinal = 0) int progress, @Local(ordinal = 0)ServerPlayerEntity serverPlayerEntity) { + private void redirectPacketSent(ServerPlayNetworkHandler instance, Packet packetBad, @Local(ordinal = 0, argsOnly = true) int entityId, @Local(ordinal = 0, argsOnly = true) BlockPos pos, @Local(ordinal = 0, argsOnly = true) int progress, @Local(ordinal = 0)ServerPlayerEntity serverPlayerEntity) { if (this.packet == null) this.packet = new BlockBreakingProgressS2CPacket(entityId, pos, progress); serverPlayerEntity.networkHandler.sendPacket(this.packet); } diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerChunkManagerMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerChunkManagerMixin.java new file mode 100644 index 0000000..3d3c72c --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerChunkManagerMixin.java @@ -0,0 +1,21 @@ +package com.github.tatercertified.potatoptimize.mixin.random.world; + +import com.github.tatercertified.potatoptimize.utils.interfaces.SnowInterface; +import net.minecraft.server.world.ServerChunkManager; +import net.minecraft.server.world.ServerWorld; +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; + +@Mixin(ServerChunkManager.class) +public class RandomServerChunkManagerMixin { + @Shadow @Final ServerWorld world; + + @Inject(method = "tickChunks", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", ordinal = 0, shift = At.Shift.AFTER)) + private void injectToTickSnow(CallbackInfo ci) { + ((SnowInterface)this.world).resetIceAndSnowTick(); + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerWorldMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerWorldMixin.java new file mode 100644 index 0000000..4e9bfc6 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomServerWorldMixin.java @@ -0,0 +1,45 @@ +package com.github.tatercertified.potatoptimize.mixin.random.world; + +import com.github.tatercertified.potatoptimize.utils.interfaces.LightningInterface; +import com.github.tatercertified.potatoptimize.utils.interfaces.SnowInterface; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.world.MutableWorldProperties; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.function.Supplier; + +@Mixin(ServerWorld.class) +public abstract class RandomServerWorldMixin extends World implements SnowInterface { + + private int currentIceAndSnowTick; + + protected RandomServerWorldMixin(MutableWorldProperties properties, RegistryKey registryRef, DynamicRegistryManager registryManager, RegistryEntry dimensionEntry, Supplier profiler, boolean isClient, boolean debugWorld, long biomeAccess, int maxChainedNeighborUpdates) { + super(properties, registryRef, registryManager, dimensionEntry, profiler, isClient, debugWorld, biomeAccess, maxChainedNeighborUpdates); + } + + @Override + public void resetIceAndSnowTick() { + this.currentIceAndSnowTick = this.random.nextInt(16); + } + + @Redirect(method = "tickChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/random/Random;nextInt(I)I", ordinal = 1)) + private int redirectIceAndSnowChance(Random instance, int i) { + return this.currentIceAndSnowTick; + } + + @Redirect(method = "tickChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;isThundering()Z")) + private boolean redirectIsThundering(ServerWorld instance, @Local(ordinal = 0, argsOnly = true) WorldChunk chunk) { + return instance.isThundering() && ((LightningInterface)chunk).shouldDoLightning(this.random); + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldChunkMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldChunkMixin.java new file mode 100644 index 0000000..ee253a8 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldChunkMixin.java @@ -0,0 +1,50 @@ +package com.github.tatercertified.potatoptimize.mixin.random.world; + +import com.github.tatercertified.potatoptimize.utils.interfaces.LightningInterface; +import com.moulberry.mixinconstraints.annotations.IfModAbsent; +import net.minecraft.registry.Registry; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.HeightLimitView; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.UpgradeData; +import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.gen.chunk.BlendingData; +import net.minecraft.world.tick.ChunkTickScheduler; +import org.jetbrains.annotations.Nullable; +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; + +@Mixin(WorldChunk.class) +public abstract class RandomWorldChunkMixin extends Chunk implements LightningInterface { + + @Shadow @Final private World world; + + public RandomWorldChunkMixin(ChunkPos pos, UpgradeData upgradeData, HeightLimitView heightLimitView, Registry biomeRegistry, long inhabitedTime, @Nullable ChunkSection[] sectionArray, @Nullable BlendingData blendingData) { + super(pos, upgradeData, heightLimitView, biomeRegistry, inhabitedTime, sectionArray, blendingData); + } + + private int lightningTick; + + @Override + public boolean shouldDoLightning(Random random) { + if (this.lightningTick-- <= 0) { + this.lightningTick = random.nextInt(100000) << 1; + return true; + } + return false; + } + + @IfModAbsent(value = "c2me-base") + @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/ChunkPos;Lnet/minecraft/world/chunk/UpgradeData;Lnet/minecraft/world/tick/ChunkTickScheduler;Lnet/minecraft/world/tick/ChunkTickScheduler;J[Lnet/minecraft/world/chunk/ChunkSection;Lnet/minecraft/world/chunk/WorldChunk$EntityLoader;Lnet/minecraft/world/gen/chunk/BlendingData;)V", at = @At("TAIL")) + private void injectRandomLightningTick(World world, ChunkPos pos, UpgradeData upgradeData, ChunkTickScheduler blockTickScheduler, ChunkTickScheduler fluidTickScheduler, long inhabitedTime, ChunkSection[] sectionArrayInitializer, WorldChunk.EntityLoader entityLoader, BlendingData blendingData, CallbackInfo ci) { + this.lightningTick = this.world.getRandom().nextInt(100000) << 1; + } +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldMixin.java index 883375b..e90839a 100644 --- a/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldMixin.java +++ b/src/main/java/com/github/tatercertified/potatoptimize/mixin/random/world/RandomWorldMixin.java @@ -1,6 +1,7 @@ package com.github.tatercertified.potatoptimize.mixin.random.world; import com.github.tatercertified.potatoptimize.utils.random.ThreadLocalRandomImpl; +import com.github.tatercertified.potatoptimize.utils.random.XorShiftRandomImpl; import com.moulberry.mixinconstraints.annotations.IfModAbsent; import net.minecraft.util.math.random.Random; import net.minecraft.world.World; @@ -8,11 +9,26 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; -@IfModAbsent(value = "faster-random") -@Mixin(World.class) +@IfModAbsent(value = "faster-random", aliases = {"c2me-fixes-worldgen-threading-issues"}) +@Mixin(value = World.class) public class RandomWorldMixin { - @Shadow @Final @Mutable @Deprecated private Random threadSafeRandom = new ThreadLocalRandomImpl(); - @Shadow @Final @Mutable public Random random = new ThreadLocalRandomImpl(); - @Shadow @Mutable protected int lcgBlockSeed = random.nextInt(); + @Shadow @Final public Random random; + + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/random/Random;create()Lnet/minecraft/util/math/random/Random;")) + private Random redirectRandomCreation() { + return new XorShiftRandomImpl(); + } + + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/random/Random;createThreadSafe()Lnet/minecraft/util/math/random/Random;")) + private Random redirectThreadSafeRandomCreation() { + return new ThreadLocalRandomImpl(); + } + + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/random/Random;nextInt()I")) + private int redirectRandomNextInt(Random instance) { + return this.random.nextInt(); + } } diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRCommandMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRCommandMixin.java deleted file mode 100644 index 791fa6b..0000000 --- a/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRCommandMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.tatercertified.potatoptimize.mixin.remove.profiler; - -import net.minecraft.server.command.JfrCommand; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(JfrCommand.class) -public class JFRCommandMixin { - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - private static int executeStart(ServerCommandSource source) { - source.sendFeedback(() -> Text.literal("JFR has been removed by Potatoptimize; Use Spark instead!"), false); - return 0; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - private static int executeStop(ServerCommandSource source) { - source.sendFeedback(() -> Text.literal("JFR has been removed by Potatoptimize; Use Spark instead!"), false); - return 0; - } -} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRMixin.java deleted file mode 100644 index c828a1c..0000000 --- a/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/JFRMixin.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.github.tatercertified.potatoptimize.mixin.remove.profiler; - -import net.minecraft.network.NetworkPhase; -import net.minecraft.network.packet.PacketType; -import net.minecraft.registry.RegistryKey; -import net.minecraft.util.function.Finishable; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.profiling.jfr.InstanceType; -import net.minecraft.util.profiling.jfr.JfrProfiler; -import net.minecraft.util.profiling.jfr.event.NetworkSummaryEvent; -import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; -import org.slf4j.LoggerFactory; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.io.Reader; -import java.net.SocketAddress; -import java.nio.file.Path; - -@Mixin(JfrProfiler.class) -public class JFRMixin { - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public boolean start(InstanceType instanceType) { - LoggerFactory.getLogger("Potatoptimize").warn("/jfr has been removed; Use spark or alternative instead!"); - return false; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public Path stop() { - return null; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public boolean isProfiling() { - return false; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public boolean isAvailable() { - return false; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - private boolean start(Reader reader, InstanceType instanceType) { - return false; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - private void addListener() { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void onTick(float tickTime) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void onPacketReceived(NetworkPhase state, PacketType type, SocketAddress remoteAddress, int bytes) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void onPacketSent(NetworkPhase state, PacketType type, SocketAddress remoteAddress, int bytes) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - private NetworkSummaryEvent.Recorder getOrCreateSummaryRecorder(SocketAddress address) { - return null; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public @Nullable Finishable startWorldLoadProfiling() { - return null; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public @Nullable Finishable startChunkGenerationProfiling(ChunkPos chunkPos, RegistryKey world, String targetStatus) { - return null; - } -} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/ProfilerSystemMixin.java b/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/ProfilerSystemMixin.java deleted file mode 100644 index 36d3bf9..0000000 --- a/src/main/java/com/github/tatercertified/potatoptimize/mixin/remove/profiler/ProfilerSystemMixin.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.github.tatercertified.potatoptimize.mixin.remove.profiler; - -import net.minecraft.util.profiler.ProfileResult; -import net.minecraft.util.profiler.ProfilerSystem; -import net.minecraft.util.profiler.SampleType; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.util.Set; -import java.util.function.Supplier; - -@Mixin(ProfilerSystem.class) -public class ProfilerSystemMixin { - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void startTick() { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void endTick() { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void push(String location) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void push(Supplier locationGetter) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void markSampleType(SampleType type) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void pop() { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void swap(String location) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void swap(Supplier locationGetter) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - private ProfilerSystem.LocatedInfo getCurrentInfo() { - return null; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void visit(String marker, int num) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public void visit(Supplier markerGetter, int num) { - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public ProfileResult getResult() { - return null; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public ProfilerSystem.@Nullable LocatedInfo getInfo(String name) { - return null; - } - - /** - * @author QPCrummer - * @reason Removal - */ - @Overwrite - public Set> getSampleTargets() { - return null; - } - -} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/InteractionLimiterInterface.java b/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/InteractionLimiterInterface.java new file mode 100644 index 0000000..1987636 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/InteractionLimiterInterface.java @@ -0,0 +1,9 @@ +package com.github.tatercertified.potatoptimize.utils.interfaces; + +public interface InteractionLimiterInterface { + int getInstaBreakCountPerTick(); + int getPlaceBlockCountPerTick(); + void addInstaBreakCountPerTick(); + void addPlaceBlockCountPerTick(); + boolean allowOperation(); +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/LightningInterface.java b/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/LightningInterface.java new file mode 100644 index 0000000..8109229 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/LightningInterface.java @@ -0,0 +1,7 @@ +package com.github.tatercertified.potatoptimize.utils.interfaces; + +import net.minecraft.util.math.random.Random; + +public interface LightningInterface { + boolean shouldDoLightning(Random random); +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/SnowInterface.java b/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/SnowInterface.java new file mode 100644 index 0000000..16042e0 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/utils/interfaces/SnowInterface.java @@ -0,0 +1,5 @@ +package com.github.tatercertified.potatoptimize.utils.interfaces; + +public interface SnowInterface { + void resetIceAndSnowTick(); +} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/utils/random/NotThreadSafeRandomImpl.java b/src/main/java/com/github/tatercertified/potatoptimize/utils/random/NotThreadSafeRandomImpl.java deleted file mode 100644 index f8a8ad7..0000000 --- a/src/main/java/com/github/tatercertified/potatoptimize/utils/random/NotThreadSafeRandomImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.github.tatercertified.potatoptimize.utils.random; - -import net.minecraft.util.math.random.Random; -import net.minecraft.util.math.random.RandomSplitter; - -import java.util.UUID; - -// TODO Finish this - -/** - * Credit to PaperMC patch #06911 - */ -public class NotThreadSafeRandomImpl implements PotatoptimizedRandom { - private final long multiplier = 0x5DEECE66DL; - private final long addend = 0xBL; - private final long mask = (1L << 48) - 1; - private long seed; - - public static final Random INSTANCE = new NotThreadSafeRandomImpl(); - - public NotThreadSafeRandomImpl(long seed) { - this.seed = seed; - } - - public NotThreadSafeRandomImpl() { - this.setSeed(nextLong()); - } - - @Override - public double nextDouble(double bound) { - return 0; - } - - @Override - public double nextDouble(double origin, double bound) { - return 0; - } - - @Override - public float nextFloat(float bound) { - return 0; - } - - @Override - public float nextFloat(float origin, float bound) { - return 0; - } - - @Override - public float nextGaussian(float mean, float deviation) { - return 0; - } - - @Override - public UUID nextUUID() { - return null; - } - - @Override - public Random split() { - return null; - } - - @Override - public RandomSplitter nextSplitter() { - return null; - } - - @Override - public void setSeed(long seed) { - this.seed = scrambleSeed(seed); - } - - @Override - public int nextInt() { - return 0; - } - - @Override - public int nextInt(int bound) { - return fastBoundedLong(this.next(32) & 0xFFFFFFFFL, bound); - } - - @Override - public long nextLong() { - return 0; - } - - @Override - public boolean nextBoolean() { - return false; - } - - @Override - public float nextFloat() { - return 0; - } - - @Override - public double nextDouble() { - return 0; - } - - @Override - public double nextGaussian() { - return 0; - } - - private long scrambleSeed(long seed) { - return (seed ^ multiplier) & mask; - } - - private int fastBoundedLong(final long randomInteger, final long limit) { - return (int)((randomInteger * limit) >>> 32); - } - - private int next(int bits) { - return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); - } -} diff --git a/src/main/java/com/github/tatercertified/potatoptimize/utils/random/XorShiftRandomImpl.java b/src/main/java/com/github/tatercertified/potatoptimize/utils/random/XorShiftRandomImpl.java new file mode 100644 index 0000000..f3bb699 --- /dev/null +++ b/src/main/java/com/github/tatercertified/potatoptimize/utils/random/XorShiftRandomImpl.java @@ -0,0 +1,227 @@ +package com.github.tatercertified.potatoptimize.utils.random; + +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.math.random.RandomSplitter; + +import java.util.UUID; + +/** + * Credit: Gale Patch #0131 + */ +public class XorShiftRandomImpl implements PotatoptimizedRandom { + + public static final Random INSTANCE = new XorShiftRandomImpl(); + + final double REAL_UNIT_INT = 1.0 / (0x7FFFFFFFL); + final double REAL_UNIT_UINT = 1.0 / (0xFFFFFFFFL); + final long Y = 842502087L, Z = 3579807591L, W = 273326509L; + long x, y, z, w; + long boolBuffer; + int boolBufferBits = 0; + + public XorShiftRandomImpl() { + seed((int) System.currentTimeMillis()); + } + + public XorShiftRandomImpl(int seed) { + seed(seed); + } + + @Override + public double nextDouble(double bound) { + return (nextLong() >>> 1) / (double) Long.MAX_VALUE * bound; + } + + @Override + public double nextDouble(double origin, double bound) { + return origin + (nextLong() >>> 1) / (double) Long.MAX_VALUE * (bound - origin); + } + + @Override + public float nextFloat(float bound) { + return (nextLong() >>> 1) / (float) Long.MAX_VALUE * bound; + } + + @Override + public float nextFloat(float origin, float bound) { + return origin + (nextLong() >>> 1) / (float) Long.MAX_VALUE * (bound - origin); + } + + @Override + public float nextGaussian(float mean, float deviation) { + return (float) (mean + deviation * nextGaussian()); + } + + @Override + public UUID nextUUID() { + long mostSigBits = nextLong(); + long leastSigBits = nextLong(); + return new UUID(mostSigBits, leastSigBits); + } + + @Override + public Random split() { + return this; + } + + @Override + public RandomSplitter nextSplitter() { + return new Splitter(0L, this); + } + + @Override + public void setSeed(long seed) { + seed((int) seed); + } + + @Override + public int nextInt() { + long t = (x ^ (x << 11)); + x = y; + y = z; + z = w; + return (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)))); + } + + @Override + public int nextInt(int bound) { + if (bound < 0) { + throw new IllegalArgumentException("upperBound must be >=0"); + } + + long t = (x ^ (x << 11)); + x = y; + y = z; + z = w; + + return (int) ((REAL_UNIT_INT * (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))) * bound); + } + + @Override + public int nextBetween(int min, int max) { + if (min > max) + throw new IllegalArgumentException("upperBound must be >=lowerBound"); + + long t = (x ^ (x << 11)); + x = y; + y = z; + z = w; + + int range = max - min; + if (range < 0) { + return min + (int) ((REAL_UNIT_UINT * (double) (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)))) * (double) ((long) max - (long) min)); + } + return min + (int) ((REAL_UNIT_INT * (double) (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))) * (double) range); + } + + @Override + public long nextLong() { + return nextUInt() << 32 + nextUInt(); + } + + @Override + public boolean nextBoolean() { + if (boolBufferBits == 0) { + boolBuffer = nextUInt(); + boolBufferBits = 32; + } + boolBuffer >>= 1; + boolean bit = (boolBuffer & 1) == 0; + --boolBufferBits; + return bit; + } + + @Override + public float nextFloat() { + return (float) nextDouble(); + } + + @Override + public double nextDouble() { + long t = (x ^ (x << 11)); + x = y; + y = z; + z = w; + return (REAL_UNIT_INT * (int) (0x7FFFFFFF & (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))))); + } + + @Override + public double nextGaussian() { + long randomBits = nextLong(); + long evenChunks = randomBits & EVEN_CHUNKS; + long oddChunks = (randomBits & ODD_CHUNKS) >>> 5; + long sum = chunkSum(evenChunks + oddChunks) - 186; + return sum / 31.0; + } + + private long chunkSum(long bits) { + long sum = bits + (bits >>> 40); + sum += sum >>> 20; + sum += sum >>> 10; + sum &= (1<<10)-1; + return sum; + } + + private final long EVEN_CHUNKS = 0x7c1f07c1f07c1fL; + private final long ODD_CHUNKS = EVEN_CHUNKS << 5; + + @Override + public double nextTriangular(double mode, double deviation) { + double u = nextDouble(); + double squareDev = 2 * deviation; + double c = (mode - deviation) / (squareDev); + if (u > c) { + u = 1.0 - u; + c = 1.0 - c; + } + return mode - deviation + (squareDev) * Math.sqrt(u * c); + } + + @Override + public int nextBetweenExclusive(int min, int max) { + return nextBetween(min + 1, max - 1); + } + + private long nextUInt() { + long t = (x ^ (x << 11)); + x = y; + y = z; + z = w; + return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))) & (0xFFFFFFFFL); + } + + + private void seed(int seed) { + x = seed; + y = Y; + z = Z; + w = W; + } + + public record Splitter(long seed, XorShiftRandomImpl instance) implements RandomSplitter { + + @Override + public Random split(String seed) { + int i = seed.hashCode(); + return new XorShiftRandomImpl((int) (i ^ instance.x)); + } + + @Override + public Random split(long seed) { + return new XorShiftRandomImpl((int) (seed ^ instance.x)); + } + + @Override + public Random split(int x, int y, int z) { + long l = MathHelper.hashCode(x, y, z); + int m = (int) (l ^ this.seed); + return new XorShiftRandomImpl(m); + } + + @Override + public void addDebugInfo(StringBuilder info) { + info.append("seed: ").append(instance.x); + } + } +} diff --git a/src/main/resources/assets/potatoptimize/potatoptimize-mixin-config-default.properties b/src/main/resources/assets/potatoptimize/potatoptimize-mixin-config-default.properties index ed77019..e52747f 100644 --- a/src/main/resources/assets/potatoptimize/potatoptimize-mixin-config-default.properties +++ b/src/main/resources/assets/potatoptimize/potatoptimize-mixin-config-default.properties @@ -18,6 +18,7 @@ mixin.entity.villager_task = true mixin.fastmath.intrinsic = true mixin.fastmath.joml = true mixin.fastmath.rounding = true +mixin.feature.interaction_limiter = true mixin.item.map_chunk_loading = true mixin.item.treasure_map_lookup = true mixin.logic.chunk_query = true diff --git a/src/main/resources/potatoptimize.mixins.json b/src/main/resources/potatoptimize.mixins.json index c377a33..1a346d7 100644 --- a/src/main/resources/potatoptimize.mixins.json +++ b/src/main/resources/potatoptimize.mixins.json @@ -21,6 +21,7 @@ "entity.halloween.ZombieEntityMixin", "entity.navigation.CancelNavigationMixin", "entity.pathfinding.MobPathfindingMixin", + "entity.pathfinding.TargetPredicateMixin", "entity.spawning.SpawnHelperMixin", "entity.speed.EntitySpeedMixin", "entity.statistics.PlayerEntityStatsMixin", @@ -36,6 +37,9 @@ "fastmath.rounding.FastRoundingServerPlayerMixin", "fastmath.rounding.FastRoundingSurfaceBuildMixin", "fastmath.rounding.FastRoundingVoxShapeMixin", + "feature.interaction_limiter.LimiterBlockItemMixin", + "feature.interaction_limiter.LimiterServerInteractionManagerMixin", + "feature.interaction_limiter.LimiterServerPlayerEntityMixin", "item.map_chunk_loading.MapChunkLoadingMixin", "item.treasure_map_lookup.FilledMapItemMixin", "logic.chunk_query.ChunkQueryMixin", @@ -70,9 +74,7 @@ "memory.reduce_alloc.NbtLongArrayMixin", "memory.reduce_alloc.PacketEncryptionManagerMixin", "memory.reduce_alloc.ServerConfigListMixin", - "unstable.reduce_random.RandomCreationMixin", "networking.block_breaking.CacheBlockBreakPacketMixin", - "unstable.explosion_packets.ExplosionNetworkingMixin", "random.creation.QueryResponseHandlerMixin", "random.creation.ServerPlayerEntityRandomMixin", "random.entity.RandomEntityMixin", @@ -82,14 +84,16 @@ "random.math.GetRandomInterface", "random.math.RandomMathHelperMixin", "random.unsafe.ForceEnableUnsafeMixin", + "random.world.RandomServerChunkManagerMixin", + "random.world.RandomServerWorldMixin", + "random.world.RandomWorldChunkMixin", "random.world.RandomWorldMixin", - "remove.profiler.JFRCommandMixin", - "remove.profiler.JFRMixin", - "remove.profiler.ProfilerSystemMixin", - "unstable.entity_ticking.EntityListMixin", - "unstable.entity_ticking.EntityServerThreadingMixin", "threading.explosions.AsyncExplosionMixin", "threading.explosions.ExplosionThreadStopMixin", + "unstable.entity_ticking.EntityListMixin", + "unstable.entity_ticking.EntityServerThreadingMixin", + "unstable.explosion_packets.ExplosionNetworkingMixin", + "unstable.reduce_random.RandomCreationMixin", "unstream.nearest_item.NearestItemSensorMixin", "unstream.nearest_item.NearestPlayersSensorMixin", "unstream.pathfinding.PatchNodeNavigatorMixin", @@ -107,8 +111,8 @@ "client": [ "fastmath.rounding.FastRoundingDebugRenderMixin", "fastmath.rounding.FastRoundingQuadsMixin", - "unstable.explosion_packets.ClientExplosionMixin", "threading.client_tick.ClientTickMixin", + "unstable.explosion_packets.ClientExplosionMixin", "unstream.recipe_manager.ClientNetworkAccessor", "unstream.recipe_manager.StreamClientPlayNetworkHandlerMixin" ],