diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java index 8ff83a9d..085c65d8 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -13,11 +15,13 @@ import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Owned; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.CasterUtils; +import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.util.NbtSerialisable; import com.mojang.authlib.GameProfile; +import net.minecraft.block.ShapeContext; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.SkullBlockEntity; import net.minecraft.entity.Entity; @@ -35,6 +39,12 @@ import net.minecraft.entity.mob.VexEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.ShulkerBulletEntity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.function.BooleanBiFunction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.WorldAccess; public class Disguise implements NbtSerialisable { @@ -298,4 +308,40 @@ public class Disguise implements NbtSerialisable { return entityNbt; } + + void getCollissionShapes(ShapeContext context, Consumer output) { + getCollissionShapes(getAppearance(), context, output); + getAttachments().forEach(e -> getCollissionShapes(e, context, output)); + } + + private static void getCollissionShapes(Entity entity, ShapeContext context, Consumer output) { + if (entity.method_30948()) { + output.accept(VoxelShapes.cuboid(entity.getBoundingBox())); + } else if (entity instanceof FallingBlockEntity) { + BlockPos pos = entity.getBlockPos(); + output.accept(((FallingBlockEntity) entity).getBlockState() + .getCollisionShape(entity.world, entity.getBlockPos(), context) + .offset(pos.getX(), pos.getY(), pos.getZ()) + ); + } + } + + public static List getColissonShapes(@Nullable Entity entity, WorldAccess world, Box box, Predicate predicate) { + List shapes = new ArrayList<>(); + ShapeContext ctx = entity == null ? ShapeContext.absent() : ShapeContext.of(entity); + VoxelShape entityShape = VoxelShapes.cuboid(box.expand(1.0E-6D)); + + world.getOtherEntities(entity, box.expand(0.5), predicate.and(e -> { + CasterUtils.toCaster(e).flatMap(c -> c.getSpellOrEmpty(DisguiseSpell.class, false)).ifPresent(p -> { + p.getDisguise().getCollissionShapes(ctx, shape -> { + if (!shape.isEmpty() && VoxelShapes.matchesAnywhere(shape, entityShape, BooleanBiFunction.AND)) { + shapes.add(shape); + } + }); + }); + return false; + })); + + return shapes; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java index 0daf9530..257ee818 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinLivingEntity.java @@ -11,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import com.minelittlepony.unicopia.ability.magic.CasterUtils; import com.minelittlepony.unicopia.ability.magic.spell.DisguiseSpell; import com.minelittlepony.unicopia.entity.Creature; import com.minelittlepony.unicopia.entity.PonyContainer; @@ -69,6 +70,18 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer info) { + CasterUtils.toCaster(this) + .flatMap(c -> c.getSpellOrEmpty(DisguiseSpell.class, false)) + .map(DisguiseSpell::getDisguise) + .map(Disguise::getAppearance) + .filter(Entity::isPushable) + .ifPresent(v -> { + info.setReturnValue(false); + }); + } + @Inject(method = "canSee(Lnet/minecraft/entity/Entity;)Z", at = @At("HEAD"), cancellable = true) private void onCanSee(Entity other, CallbackInfoReturnable info) { if (get().isInvisible()) { diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java new file mode 100644 index 00000000..4a981b2a --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java @@ -0,0 +1,31 @@ +package com.minelittlepony.unicopia.mixin; + +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import javax.annotation.Nullable; + +import org.spongepowered.asm.mixin.Mixin; +import com.minelittlepony.unicopia.entity.behaviour.Disguise; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.Box; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; + +@Mixin(World.class) +abstract class MixinWorld implements WorldAccess { + @Override + public Stream getEntityCollisions(@Nullable Entity entity, Box box, Predicate predicate) { + if (box.getAverageSideLength() >= 1.0E-7D) { + List shapes = Disguise.getColissonShapes(entity, this, box, predicate); + if (!shapes.isEmpty()) { + return Stream.concat(shapes.stream(), WorldAccess.super.getEntityCollisions(entity, box, predicate)); + } + } + + return WorldAccess.super.getEntityCollisions(entity, box, predicate); + } +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 98adfcbc..663a9fac 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -17,7 +17,8 @@ "MixinServerPlayerEntity", "MixinSheepEntity", "MixinShulkerEntity", - "MixinTargetPredicate" + "MixinTargetPredicate", + "MixinWorld" ], "client": [ "client.MixinCamera",