Skip to content

让我们融为一体吧

无实体碰撞

在某些情况下,你可能需要让实体之间不会发生碰撞。这个案例实现了在实体拥有无碰撞 NO_COLLISION 效果时取消碰撞判定。

java
@Mixin(LivingEntity.class)
public abstract class LevelEntityMixin {
    @Unique
    private final Predicate<Entity> mod$noCollisionEffect = entity -> !(entity instanceof LivingEntity living) || !living.hasEffect(ModEffects.NO_COLLISION.get());
    @Unique
    private final Predicate<Entity> mod$alwaysFalse = entity -> false;
    
    @Redirect(method = "pushEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntitySelector;pushableBy(Lnet/minecraft/world/entity/Entity;)Ljava/util/function/Predicate;"))
    public Predicate<Entity> mixin$getEntities(Entity entity) {
        if (((LivingEntity) (Object)this).hasEffect(ModEffects.NO_COLLISION.get())) {
            return mod$alwaysFalse;//如果实体本身拥有效果,则不对任何实体产生碰撞。
        }
        
        //不对拥有效果的实体产生碰撞
        return EntitySelector.pushableBy((Entity) (Object)this).and(mod$noCollisionEffect);
    }
}

实体的碰撞分为两个部分

  • 当前实体对其他实体的碰撞
  • 其他实体对当前实体的碰撞

因此,需要将两部分都取消。幸运的是,这两部分都通过调用 pushEntities 方法来进行碰撞检测。所以,只需要在获取实体时作下手脚,给判定实体的条件(Predicate)添加上对无碰撞效果的检测。