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 String username;
private long lastSkinUpdate = -1; private long lastSkinUpdate = -1;
private boolean playerList = true; private boolean playerList = true;
private boolean onGround;
private final EntityEffectCache effectCache; private final EntityEffectCache effectCache;
private Entity leftParrot; private Entity leftParrot;
@ -143,6 +144,8 @@ public class PlayerEntity extends LivingEntity {
setPosition(position); setPosition(position);
setRotation(rotation); setRotation(rotation);
this.onGround = isOnGround;
MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId); movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(this.position); movePlayerPacket.setPosition(this.position);
@ -168,6 +171,8 @@ public class PlayerEntity extends LivingEntity {
setRotation(rotation); setRotation(rotation);
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
this.onGround = isOnGround;
MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId); movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(position); 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()); Vector3f rotation = Vector3f.from(packet.getRotation().getY(), packet.getRotation().getX(), packet.getRotation().getY());
entity.setPosition(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0)); entity.setPosition(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0));
entity.setRotation(rotation); entity.setRotation(rotation);
entity.setOnGround(packet.isOnGround());
/* /*
boolean colliding = false; boolean colliding = false;

View file

@ -79,7 +79,7 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
itemEntry = Translators.getItemTranslator().getItem(item); itemEntry = Translators.getItemTranslator().getItem(item);
nbtData = item.getNbt(); 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)); levelEvent.setData((int) (65535 / breakTime));
session.setBreakingBlock(packet.getNewState()); session.setBreakingBlock(packet.getNewState());
session.sendUpstreamPacket(levelEvent); session.sendUpstreamPacket(levelEvent);

View file

@ -26,8 +26,10 @@
package org.geysermc.connector.network.translators.world; 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.github.steveice10.mc.protocol.data.game.world.block.BlockState;
import com.nukkitx.math.vector.Vector3i;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
/** /**
@ -39,6 +41,28 @@ import org.geysermc.connector.network.session.GeyserSession;
*/ */
public abstract class WorldManager { 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 * Gets the {@link BlockState} at the specified location
* *

View file

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