Cast, Convert & more

This commit is contained in:
skippyall
2026-03-16 23:01:58 +01:00
parent 9b61dba4c7
commit 7acd083e79
59 changed files with 1207 additions and 178 deletions
@@ -4,8 +4,13 @@ import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.stream.Stream;
@Mixin(Entity.class)
public interface EntityAccessor {
@Invoker("canAddPassenger")
boolean invokeCanAddPassenger(Entity other);
boolean minions$canAddPassenger(Entity other);
@Invoker("streamIntoPassengers")
Stream<Entity> minions$streamIntoPassengers();
}
@@ -0,0 +1,42 @@
package io.github.skippyall.minions.mixins;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.PistonBlockEntity;
import net.minecraft.block.piston.PistonBehavior;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(PistonBlockEntity.class)
public abstract class PistonMovingBlockEntityMixin {
@WrapOperation(method = "pushEntities", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/Entity;getPistonBehavior()Lnet/minecraft/block/piston/PistonBehavior;"
))
private static PistonBehavior moveFakePlayers(Entity entity, Operation<PistonBehavior> original, World world, BlockPos pos, float f, PistonBlockEntity pistonBlockEntity)
{
if (entity instanceof MinionFakePlayer && pistonBlockEntity.getPushedBlock().isOf(Blocks.SLIME_BLOCK))
{
Vec3d vec3d = entity.getVelocity();
double x = vec3d.x;
double y = vec3d.y;
double z = vec3d.z;
Direction direction = pistonBlockEntity.getMovementDirection();
switch (direction.getAxis()) {
case X -> x = direction.getOffsetX();
case Y -> y = direction.getOffsetY();
case Z -> z = direction.getOffsetZ();
}
entity.setVelocity(x, y, z);
}
return original.call(entity);
}
}
@@ -1,20 +1,21 @@
package io.github.skippyall.minions.mixins;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import io.github.skippyall.minions.mixinhelper.EntityViewMixinHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.SpawnHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(SpawnHelper.class)
public class SpawnHelperMixin {
@Redirect(method = "spawnEntitiesInChunk(Lnet/minecraft/entity/SpawnGroup;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/SpawnHelper$Checker;Lnet/minecraft/world/SpawnHelper$Runner;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;getClosestPlayer(DDDDZ)Lnet/minecraft/entity/player/PlayerEntity;"))
private static PlayerEntity checkMobSpawningMinion(ServerWorld instance, double x, double y, double z, double maxDistance, boolean b) {
return instance.getClosestPlayer(x, y, z, maxDistance, EntityPredicates.EXCEPT_SPECTATOR.and(entity -> {
@WrapOperation(method = "spawnEntitiesInChunk(Lnet/minecraft/entity/SpawnGroup;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/Chunk;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/SpawnHelper$Checker;Lnet/minecraft/world/SpawnHelper$Runner;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;getClosestPlayer(DDDDZ)Lnet/minecraft/entity/player/PlayerEntity;"))
private static PlayerEntity checkMobSpawningMinion(ServerWorld world, double x, double y, double z, double maxDistance, boolean ignoreCreative, Operation<PlayerEntity> original) {
EntityViewMixinHelper.ADDITIONAL_PREDICATE.set(entity -> {
if(entity instanceof ServerPlayerEntity player) {
if(player instanceof MinionFakePlayer minion) {
return minion.canSpawnMobs();
@@ -22,6 +23,9 @@ public class SpawnHelperMixin {
return true;
}
return false;
}));
});
PlayerEntity player = original.call(world, x, y, z, maxDistance, ignoreCreative);
EntityViewMixinHelper.ADDITIONAL_PREDICATE.remove();
return player;
}
}
@@ -0,0 +1,33 @@
package io.github.skippyall.minions.mixins;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import io.github.skippyall.minions.minion.fakeplayer.MinionFakePlayer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.tick.TickManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(TickManager.class)
public abstract class TickRateManagerMixin {
@Shadow
public abstract boolean shouldTick();
@ModifyReturnValue(method = "shouldSkipTick", at = @At("TAIL"))
private boolean handler(boolean alreadyFrozen, Entity entity) {
if (alreadyFrozen) return true;
if (shouldTick()) return false;
return !isActualPlayer(entity) && // not carrying players
((EntityAccessor) entity)
.minions$streamIntoPassengers()
.noneMatch(TickRateManagerMixin::isActualPlayer);
}
@Unique
private static boolean isActualPlayer(Entity e) {
return e instanceof PlayerEntity && !(e instanceof MinionFakePlayer);
}
}