Skip to content

Commit

Permalink
Additional optimizations from Leaves
Browse files Browse the repository at this point in the history
- Fixed c2me compatibility
- Improvements to random
- Improvements to JRC removal
- Added a player interaction limiter
- Improved AI ticking
  • Loading branch information
QPCrummer committed Jun 25, 2024
1 parent 4ef5709 commit 4382448
Show file tree
Hide file tree
Showing 21 changed files with 553 additions and 427 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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<Boolean> 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();
}
}
Original file line number Diff line number Diff line change
@@ -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<ActionResult> cir) {
ServerPlayerEntity player = (ServerPlayerEntity) context.getPlayer();
if (player != null && this.getPlacementState(context) != null) {
((InteractionLimiterInterface)player).addPlaceBlockCountPerTick();
if (!((InteractionLimiterInterface)player).allowOperation()) {
cir.setReturnValue(ActionResult.FAIL);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<PairList> 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<PairList> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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<World> registryRef, DynamicRegistryManager registryManager, RegistryEntry<DimensionType> dimensionEntry, Supplier<Profiler> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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<Biome> 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 = "<init>(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;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
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;
import org.spongepowered.asm.mixin.Final;
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 = "<init>", 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 = "<init>", 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 = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/random/Random;nextInt()I"))
private int redirectRandomNextInt(Random instance) {
return this.random.nextInt();
}
}

This file was deleted.

Loading

0 comments on commit 4382448

Please sign in to comment.