水和熔岩

    From Minecraft Parkour Wiki
    This page is a translated version of the page Water and Lava and the translation is 100% complete.
    Other languages:

    [半成品]


    基础

    当玩家在水中或熔岩中移动时,游戏并不会考虑玩家是否在地面上,而只考虑玩家是否按下空格。

    离开液体时 -> 以 0.3 初始速度跳跃

    水的碰撞箱:0.998 x 0.598 x 0.998(1x0.6x1 向内缩回 0.001)

    岩浆的碰撞箱:0.8 x 0.6 x 0.8 (1x0.6x1 向内缩 0.1,Y 除外)


    按下跳跃时:threshold(motY*0.8 - 0.02) + 0.04

    其它情况:threshold(motY*0.8 - 0.02)


    这个 threshold 其实很重要,因为玩家的 motY 在第一 tick 移动之后是 -0.004。

    而 1.8 中,玩家在第二个 tick 上的速度是 0.04,


    待完成:X/Z 运动


    熔岩

    按下跳跃时:threshold(motY*0.5 - 0.02) + 0.04

    其它情况:threshold(motY*0.5 - 0.02)


    待完成:X/Z 运动


    代码

    流动的水:
    /* 摘自 Entity.java */
    public boolean handleWaterMovement()
    {
        if (world.handleWater(this.getEntityBoundingBox().contract(0.001, 0.401, 0.001), Material.water, this))
        {
            this.fallDistance = 0.0F;
            this.inWater = true;
            this.fire = 0;
        }
    
        else
        {
            this.inWater = false;
        }
    
        return this.inWater;
    }
    
    
    /* 摘自 World.java */
    public boolean handleWater(AxisAlignedBB bb, Material materialIn, Entity entityIn)
    {
        int minX = MathHelper.floor_double(bb.minX);
        int maxX = MathHelper.floor_double(bb.maxX + 1.0D);
        int minY = MathHelper.floor_double(bb.minY);
        int maxY = MathHelper.floor_double(bb.maxY + 1.0D);
        int minZ = MathHelper.floor_double(bb.minZ);
        int maxZ = MathHelper.floor_double(bb.maxZ + 1.0D);
    
        {
            boolean inWater = false;
            Vec3 acceleration = new Vec3(0.0D, 0.0D, 0.0D);
            BlockPos.MutableBlockPos blockpos = new BlockPos.MutableBlockPos();
    
            for (int x = minX; x < maxX; ++x)
            {
                for (int y = minY; y < maxY; ++y)
                {
                    for (int z = minZ; z < maxZ; ++z)
                    {
                        blockpos.mutate(x, y, z);
                        IBlockState iblockstate = this.getBlockState(blockpos);
                        Block block = iblockstate.getBlock();
    
                        if (block.getMaterial() == materialIn)
                        {
                            double level = y + 1 -BlockLiquid.getLiquidHeightPercent(iblockstate.getValue(BlockLiquid.LEVEL));
                            //liquidHeightPercent(i) 返回 (i + 1) / 9.0F;
    
                            if (maxY >= level)
                            {
                                inWater = true;
                                acceleration = block.modifyAcceleration(this, blockpos, entityIn, acceleration);
                            }
                        }
                    }
                }
            }
    
            if (acceleration.lengthVector() > 0.0D && entityIn.isPushedByWater())
            {
                acceleration = acceleration.normalize();
                double mult = 0.014D;
                entityIn.motionX += acceleration.xCoord * mult;
                entityIn.motionY += acceleration.yCoord * mult;
                entityIn.motionZ += acceleration.zCoord * mult;
            }
    
            return inWater;
        }
    }
    
    
    /* 摘自 BlockLiquid.java */
    public Vec3 modifyAcceleration(World worldIn, BlockPos pos, Entity entityIn, Vec3 motion)
    {
        return motion.add(this.getFlowVector(worldIn, pos));
    }
    
    ...