diff --git a/src/main/java/net/gensokyoreimagined/nitori/common/chunkwatching/PlayerClientVDTracking.java b/src/main/java/net/gensokyoreimagined/nitori/common/chunkwatching/PlayerClientVDTracking.java new file mode 100644 index 0000000..251fba9 --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/common/chunkwatching/PlayerClientVDTracking.java @@ -0,0 +1,9 @@ +package net.gensokyoreimagined.nitori.common.chunkwatching; + +public interface PlayerClientVDTracking { + + boolean isClientViewDistanceChanged(); + + int getClientViewDistance(); + +} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/entity/fast_hand_swing/LivingEntityMixin.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/entity/fast_hand_swing/LivingEntityMixin.java new file mode 100644 index 0000000..ccf7cdf --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/entity/fast_hand_swing/LivingEntityMixin.java @@ -0,0 +1,28 @@ +package net.gensokyoreimagined.nitori.mixin.entity.fast_hand_swing; + +import net.minecraft.world.entity.LivingEntity; +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(LivingEntity.class) +public abstract class LivingEntityMixin { + @Shadow + public boolean swinging; + + @Shadow + public int swingTime; + + @Inject( + method = "updateSwingTime", + at = @At("HEAD"), + cancellable = true + ) + private void skipGetDuration(CallbackInfo ci) { + if (!this.swinging && this.swingTime == 0) { + ci.cancel(); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/MixinChunkFilter.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/MixinChunkFilter.java new file mode 100644 index 0000000..0c04e76 --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/MixinChunkFilter.java @@ -0,0 +1,22 @@ +package net.gensokyoreimagined.nitori.mixin.playerwatching; + +import net.minecraft.server.level.ChunkTrackingView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(ChunkTrackingView.class) +public interface MixinChunkFilter { + + /** + * @author ishland + * @reason use chebyshev distance + */ + @Overwrite + static boolean isWithinDistance(int centerX, int centerZ, int viewDistance, int x, int z, boolean includeEdge) { + int actualViewDistance = viewDistance + (includeEdge ? 1 : 0); + int xDistance = Math.abs(centerX - x); + int zDistance = Math.abs(centerZ - z); + return xDistance <= actualViewDistance && zDistance <= actualViewDistance; + } + +} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/MixinServerPlayerEntity.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/MixinServerPlayerEntity.java new file mode 100644 index 0000000..5357e9b --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/MixinServerPlayerEntity.java @@ -0,0 +1,46 @@ +package net.gensokyoreimagined.nitori.mixin.playerwatching; + +import net.gensokyoreimagined.nitori.common.chunkwatching.PlayerClientVDTracking; +import net.minecraft.server.level.ClientInformation; +import net.minecraft.server.level.ServerPlayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerPlayer.class) +public class MixinServerPlayerEntity implements PlayerClientVDTracking { + + @Unique + private boolean vdChanged = false; + + @Unique + private int clientVD = 2; + + @Inject(method = "updateOptions", at = @At("HEAD")) + private void onClientSettingsChanged(ClientInformation packet, CallbackInfo ci) { + final int currentVD = packet.viewDistance(); + if (currentVD != this.clientVD) this.vdChanged = true; + this.clientVD = Math.max(2, currentVD); + } + + @Inject(method = "restoreFrom", at = @At("RETURN")) + private void onPlayerCopy(ServerPlayer oldPlayer, boolean alive, CallbackInfo ci) { + this.clientVD = ((PlayerClientVDTracking) oldPlayer).getClientViewDistance(); + this.vdChanged = true; + } + + @Unique + @Override + public boolean isClientViewDistanceChanged() { + return this.vdChanged; + } + + @Unique + @Override + public int getClientViewDistance() { + this.vdChanged = false; + return this.clientVD; + } +} \ No newline at end of file diff --git a/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/optimize_nearby_player_lookups/MixinMobEntity.java b/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/optimize_nearby_player_lookups/MixinMobEntity.java new file mode 100644 index 0000000..3a4e019 --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/mixin/playerwatching/optimize_nearby_player_lookups/MixinMobEntity.java @@ -0,0 +1,35 @@ +package net.gensokyoreimagined.nitori.mixin.playerwatching.optimize_nearby_player_lookups; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.List; +import java.util.function.Predicate; + +@Mixin(Mob.class) +public abstract class MixinMobEntity extends LivingEntity { + + protected MixinMobEntity(EntityType entityType, Level world) { + super(entityType, world); + } + + @Redirect(method = "checkDespawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;findNearbyPlayer(Lnet/minecraft/world/entity/Entity;DLjava/util/function/Predicate;)Lnet/minecraft/world/entity/player/Player;")) + private Player redirectGetClosestPlayer(Level instance, Entity entity, double v, Predicate predicate) { + final Player closestPlayer = instance.getNearestPlayer(entity, this.getType().getCategory().getDespawnDistance()); + if (closestPlayer != null) { + return closestPlayer; + } else { + final List players = this.level().players(); + if (players.isEmpty()) return null; + return players.get(0); + } + } + +} \ No newline at end of file diff --git a/src/main/resources/mixins.core.json b/src/main/resources/mixins.core.json index 591967e..e219f15 100755 --- a/src/main/resources/mixins.core.json +++ b/src/main/resources/mixins.core.json @@ -39,6 +39,7 @@ "shapes.blockstate_cache.BlockMixin", "shapes.lazy_shape_context.EntityShapeContextMixin", "entity.fast_retrieval.SectionedEntityCacheMixin", + "entity.fast_hand_swing.LivingEntityMixin", "math.fast_blockops.DirectionMixin", "math.fast_blockops.BlockPosMixin", "math.fast_util.AxisCycleDirectionMixin$ForwardMixin", @@ -61,6 +62,8 @@ "util.accessors.EntityTrackingSectionAccessor", "util.accessors.ServerEntityManagerAccessor", "util.block_tracking.AbstractBlockStateMixin", - "MixinEntityTickList" + "playerwatching.MixinChunkFilter", + "playerwatching.MixinServerPlayerEntity", + "playerwatching.optimize_nearby_player_lookups.MixinMobEntity" ] }