forked from GeyserMC/Geyser
Fix block breaking animations when in water (Closes #494)
This commit is contained in:
parent
99f69b3a7d
commit
0574feb87e
5 changed files with 56 additions and 17 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue