Fix block breaking animations when in water (Closes #494)

This commit is contained in:
RednedEpic 2020-05-23 18:26:20 -05:00
parent 99f69b3a7d
commit 0574feb87e
5 changed files with 56 additions and 17 deletions

View File

@ -57,6 +57,7 @@ public class PlayerEntity extends LivingEntity {
private String username;
private long lastSkinUpdate = -1;
private boolean playerList = true;
private boolean onGround;
private final EntityEffectCache effectCache;
private Entity leftParrot;
@ -143,6 +144,8 @@ public class PlayerEntity extends LivingEntity {
setPosition(position);
setRotation(rotation);
this.onGround = isOnGround;
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(this.position);
@ -168,6 +171,8 @@ public class PlayerEntity extends LivingEntity {
setRotation(rotation);
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
this.onGround = isOnGround;
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(position);

View File

@ -85,6 +85,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
Vector3f rotation = Vector3f.from(packet.getRotation().getY(), packet.getRotation().getX(), packet.getRotation().getY());
entity.setPosition(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0));
entity.setRotation(rotation);
entity.setOnGround(packet.isOnGround());
/*
boolean colliding = false;

View File

@ -79,7 +79,7 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
itemEntry = Translators.getItemTranslator().getItem(item);
nbtData = item.getNbt();
}
double breakTime = Math.ceil(BlockUtils.getBreakTime(blockHardness, packet.getNewState().getId(), itemEntry, nbtData, session.getPlayerEntity()) * 20);
double breakTime = Math.ceil(BlockUtils.getBreakTime(blockHardness, packet.getNewState().getId(), itemEntry, nbtData, session) * 20);
levelEvent.setData((int) (65535 / breakTime));
session.setBreakingBlock(packet.getNewState());
session.sendUpstreamPacket(levelEvent);

View File

@ -26,8 +26,10 @@
package org.geysermc.connector.network.translators.world;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
import com.nukkitx.math.vector.Vector3i;
import org.geysermc.connector.network.session.GeyserSession;
/**
@ -39,6 +41,28 @@ import org.geysermc.connector.network.session.GeyserSession;
*/
public abstract class WorldManager {
/**
* Gets the {@link BlockState} at the specified location
*
* @param session the session
* @param position the position
* @return the block state at the specified location
*/
public BlockState getBlockAt(GeyserSession session, Position position) {
return this.getBlockAt(session, position.getX(), position.getY(), position.getZ());
}
/**
* Gets the {@link BlockState} at the specified location
*
* @param session the session
* @param vector the position
* @return the block state at the specified location
*/
public BlockState getBlockAt(GeyserSession session, Vector3i vector) {
return this.getBlockAt(session, vector.getX(), vector.getY(), vector.getZ());
}
/**
* Gets the {@link BlockState} at the specified location
*

View File

@ -26,12 +26,15 @@
package org.geysermc.connector.utils;
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ToolItemEntry;
import java.util.Optional;
public class BlockUtils {
private static boolean correctTool(String blockToolType, String itemToolType) {
@ -63,8 +66,8 @@ public class BlockUtils {
//http://minecraft.gamepedia.com/Breaking
private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool,
String toolType, boolean isWoolBlock, boolean isCobweb, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel
/*boolean insideOfWaterWithoutAquaAffinity, boolean outOfWaterButNotOnGround*/) {
String toolType, boolean isWoolBlock, boolean isCobweb, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel,
boolean insideOfWaterWithoutAquaAffinity, boolean outOfWaterButNotOnGround, boolean insideWaterAndNotOnGround) {
double baseTime = ((correctTool || canHarvestWithHand) ? 1.5 : 5.0) * blockHardness;
double speed = 1.0 / baseTime;
@ -93,13 +96,13 @@ public class BlockUtils {
break;
}
//if (insideOfWaterWithoutAquaAffinity) speed *= 0.2;
//if (outOfWaterButNotOnGround) speed *= 0.2;
// else if insideWaterAndNotOnGround speed *= 0.2;
if (insideOfWaterWithoutAquaAffinity) speed *= 0.2;
if (outOfWaterButNotOnGround) speed *= 0.2;
if (insideWaterAndNotOnGround) speed *= 0.2;
return 1.0 / speed;
}
public static double getBreakTime(double blockHardness, int blockId, ItemEntry item, CompoundTag nbtData, PlayerEntity player) {
public static double getBreakTime(double blockHardness, int blockId, ItemEntry item, CompoundTag nbtData, GeyserSession session) {
boolean isWoolBlock = BlockTranslator.JAVA_RUNTIME_WOOL_IDS.contains(blockId);
boolean isCobweb = blockId == BlockTranslator.JAVA_RUNTIME_COBWEB_ID;
String blockToolType = BlockTranslator.JAVA_RUNTIME_ID_TO_TOOL_TYPE.getOrDefault(blockId, "");
@ -117,16 +120,22 @@ public class BlockUtils {
int hasteLevel = 0;
int miningFatigueLevel = 0;
if (player != null) {
hasteLevel = player.getEffectCache().getEffectLevel(Effect.FASTER_DIG);
miningFatigueLevel = player.getEffectCache().getEffectLevel(Effect.SLOWER_DIG);
if (session == null) {
return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, false, false);
}
// TODO implement these checks and material check if possible
//boolean insideOfWaterWithoutAquaAffinity = player.isInsideOfWater() &&
// Optional.ofNullable(player.getInventory().getHelmet().getEnchantment(Enchantment.ID_WATER_WORKER))
// .map(Enchantment::getLevel).map(l -> l >= 1).orElse(false);
//boolean outOfWaterButNotOnGround = (!player.isInsideOfWater()) && (!player.isOnGround());
return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel);
hasteLevel = session.getPlayerEntity().getEffectCache().getEffectLevel(Effect.FASTER_DIG);
miningFatigueLevel = session.getPlayerEntity().getEffectCache().getEffectLevel(Effect.SLOWER_DIG);
boolean isInWater = session.getConnector().getConfig().isCacheChunks()
&& BlockTranslator.getBedrockBlockId(session.getConnector().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt())) == BlockTranslator.BEDROCK_WATER_ID;
boolean insideOfWaterWithoutAquaAffinity = isInWater &&
ItemUtils.getEnchantmentLevel(Optional.ofNullable(session.getInventory().getItem(5)).map(ItemStack::getNbt).orElse(null), "minecraft:aqua_affinity") < 1;
boolean outOfWaterButNotOnGround = (!isInWater) && (!session.getPlayerEntity().isOnGround());
boolean insideWaterNotOnGround = isInWater && !session.getPlayerEntity().isOnGround();
return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, outOfWaterButNotOnGround, insideWaterNotOnGround);
}
}