diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 24ec4a3c7..859257bb2 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -52,6 +52,7 @@ public class Inventory { @Setter protected String title; + @Getter @Setter protected ItemStack[] items; diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index a11ce856b..52fb786bc 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -50,6 +50,6 @@ public class PlayerInventory extends Inventory { } public ItemStack getItemInHand() { - return items[heldItemSlot]; + return items[36 + heldItemSlot]; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 18ac3e6dc..4b4f66db4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -32,9 +32,9 @@ import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTInputStream; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.ListTag; -import gnu.trove.map.TObjectIntMap; -import gnu.trove.map.hash.TObjectIntHashMap; import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.Toolbox; @@ -52,6 +52,8 @@ public class BlockTranslator { private static final IntSet WATERLOGGED = new IntOpenHashSet(); private static final Map<BlockState, String> JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); + public static final Int2FloatMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2FloatOpenHashMap(); + private static final int BLOCK_STATE_VERSION = 17760256; @@ -81,7 +83,9 @@ public class BlockTranslator { } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); } - TObjectIntMap<CompoundTag> addedStatesMap = new TObjectIntHashMap<>(512, 0.5f, -1); + + Object2IntMap<CompoundTag> addedStatesMap = new Object2IntOpenHashMap<>(); + List<CompoundTag> paletteList = new ArrayList<>(); int waterRuntimeId = -1; @@ -94,6 +98,11 @@ public class BlockTranslator { String javaId = entry.getKey(); BlockState javaBlockState = new BlockState(javaRuntimeId); CompoundTag blockTag = buildBedrockState(entry.getValue()); + // TODO fix this, (no block should have a null hardness) + JsonNode hardnessNode = entry.getValue().get("block_hardness"); + if (hardnessNode != null) { + JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.floatValue()); + } JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); @@ -118,7 +127,7 @@ public class BlockTranslator { addedStatesMap.put(blockTag, bedrockRuntimeId); paletteList.add(runtimeTag); } else { - int duplicateRuntimeId = addedStatesMap.get(blockTag); + int duplicateRuntimeId = addedStatesMap.getOrDefault(blockTag, -1); if (duplicateRuntimeId == -1) { GeyserConnector.getInstance().getLogger().debug("Mapping " + javaId + " was not found for bedrock edition!"); } else { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java index 5deb0370a..bf4d19fc5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java @@ -49,11 +49,17 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ if (action.getSource().getContainerId() == ContainerId.INVENTORY) { //hotbar if (slotnum >= 9) { + // TODO REMOVE + System.out.println(slotnum); return slotnum + this.size - 9; } else { + // TODO REMOVE + System.out.println(slotnum); return slotnum + this.size + 27; } } + // TODO REMOVE + System.out.println(slotnum); return slotnum; } @@ -62,11 +68,17 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ if (slot >= this.size) { final int tmp = slot - this.size; if (tmp < 27) { + // TODO REMOVE + System.out.println(slot); return tmp + 9; } else { + // TODO REMOVE + System.out.println(slot); return tmp - 27; } } + // TODO REMOVE + System.out.println(slot); return slot; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index fd4f0b020..b9d515e9e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -32,7 +32,7 @@ import lombok.Getter; @AllArgsConstructor public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0); + public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0/*, "none", "none"*/); private String javaIdentifier; private int javaId; @@ -40,6 +40,9 @@ public class ItemEntry { private int bedrockId; private int bedrockData; + //private String toolType; + //private String toolTier; + @Override public boolean equals(Object obj) { return obj == this || (obj instanceof ItemEntry && ((ItemEntry) obj).getBedrockId() == this.getBedrockId() && ((ItemEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 451081a1a..1f0482563 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -25,10 +25,22 @@ package org.geysermc.connector.network.translators.java.entity.player; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.ChunkUtils; +import org.geysermc.connector.utils.Toolbox; + +import java.util.Arrays; public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayerActionAckPacket> { @@ -38,6 +50,137 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer case FINISH_DIGGING: ChunkUtils.updateBlock(session, packet.getNewState(), packet.getPosition()); break; + + case START_DIGGING: { + LevelEventPacket levelEvent = new LevelEventPacket(); + levelEvent.setType(LevelEventType.BLOCK_START_BREAK); + levelEvent.setPosition(Vector3f.from( + packet.getPosition().getX(), + packet.getPosition().getY(), + packet.getPosition().getZ() + )); + float blockHardness = BlockTranslator.JAVA_RUNTIME_ID_TO_HARDNESS.get(packet.getNewState().getId()); + + PlayerInventory inventory = session.getInventory(); + ItemStack[] items = inventory.getItems(); + System.out.println(Arrays.deepToString(items)); + for (int i = 0; i != items.length; i++) { + System.out.println("(" + i + ") " + items[i]); + } + int itemHandSlot = inventory.getHeldItemSlot(); + System.out.println(itemHandSlot); + ItemStack item = inventory.getItemInHand(); + System.out.println(item); + /*if (itemStack.getNbt() == null) { + itemStack = new ItemStack(itemStack.getId(), itemStack.getAmount(), new CompoundTag("")); + }*/ + //ItemEntry item = Toolbox.ITEM_ENTRIES.get(itemStack.getId()); + //System.out.println(item); + double breakTime = Math.ceil(getBreakTime(blockHardness, packet.getNewState().getId()/*, item*/) * 20); + levelEvent.setData((int) (65535 / breakTime)); + session.getUpstream().sendPacket(levelEvent); + break; + } + + case CANCEL_DIGGING: { + LevelEventPacket levelEvent = new LevelEventPacket(); + levelEvent.setType(LevelEventType.BLOCK_STOP_BREAK); + levelEvent.setPosition(Vector3f.from( + packet.getPosition().getX(), + packet.getPosition().getY(), + packet.getPosition().getZ() + )); + levelEvent.setData(0); + session.getUpstream().sendPacket(levelEvent); + break; + } } } + + private double toolBreakTimeBonus0( + /*String toolType,*/ String toolTier/*, boolean isWoolBlock, boolean isCobweb*/) { + //if (toolType == ItemTool.TYPE_SWORD) return isCobweb ? 15.0 : 1.0; + //if (toolType == ItemTool.TYPE_SHEARS) return isWoolBlock ? 5.0 : 15.0; + //if (toolType == ItemTool.TYPE_NONE) return 1.0; + switch (toolTier) { + case "wooden": + return 2.0; + case "stone": + return 4.0; + case "iron": + return 6.0; + case "diamond": + return 8.0; + case "golden": + return 12.0; + default: + return 1.0; + } + } + + /*private static double speedBonusByEfficiencyLore0(int efficiencyLoreLevel) { + if (efficiencyLoreLevel == 0) return 0; + return efficiencyLoreLevel * efficiencyLoreLevel + 1; + }*/ + + /*private static double speedRateByHasteLore0(int hasteLoreLevel) { + return 1.0 + (0.2 * hasteLoreLevel); + }*/ + + /*private static int toolType0(Item item) { + if (item.isSword()) return ItemTool.TYPE_SWORD; + if (item.isShovel()) return ItemTool.TYPE_SHOVEL; + if (item.isPickaxe()) return ItemTool.TYPE_PICKAXE; + if (item.isAxe()) return ItemTool.TYPE_AXE; + if (item.isShears()) return ItemTool.TYPE_SHEARS; + return ItemTool.TYPE_NONE; + }*/ + + /*private static boolean correctTool0(int blockToolType, Item item) { + return (blockToolType == ItemTool.TYPE_SWORD && item.isSword()) || + (blockToolType == ItemTool.TYPE_SHOVEL && item.isShovel()) || + (blockToolType == ItemTool.TYPE_PICKAXE && item.isPickaxe()) || + (blockToolType == ItemTool.TYPE_AXE && item.isAxe()) || + (blockToolType == ItemTool.TYPE_SHEARS && item.isShears()) || + blockToolType == ItemTool.TYPE_NONE; + }*/ + + //http://minecraft.gamepedia.com/Breaking + private double breakTime0(double blockHardness/*, String toolTier*/ + /*double blockHardness, boolean correctTool, boolean canHarvestWithHand, + int blockId, int toolType, String toolTier, int efficiencyLoreLevel, int hasteEffectLevel, + boolean insideOfWaterWithoutAquaAffinity, boolean outOfWaterButNotOnGround*/) { + double baseTime = (/*(correctTool || canHarvestWithHand)*/true ? 1.5 : 5.0) * blockHardness; + double speed = 1.0 / baseTime; + //boolean isWoolBlock = blockId == Block.WOOL, isCobweb = blockId == Block.COBWEB; + //if (correctTool) + //speed *= toolBreakTimeBonus0(toolTier/*toolType, toolTier, isWoolBlock, isCobweb*/); + //speed += speedBonusByEfficiencyLore0(efficiencyLoreLevel); + //speed *= speedRateByHasteLore0(hasteEffectLevel); + //if (insideOfWaterWithoutAquaAffinity) speed *= 0.2; + //if (outOfWaterButNotOnGround) speed *= 0.2; + return 1.0 / speed; + } + + private double getBreakTime(double blockHardness, int blockId/*, ItemEntry item*/) { + //Objects.requireNonNull(item, "getBreakTime: Item can not be null"); + //Objects.requireNonNull(player, "getBreakTime: Player can not be null"); + //boolean correctTool = correctTool0(getToolType(), item); + //boolean canHarvestWithHand = canHarvestWithHand(); + //int blockId = getId(); + //int itemToolType = toolType0(item); + //int itemTier = item.getTier(); + //int efficiencyLoreLevel = Optional.ofNullable(item.getEnchantment(Enchantment.ID_EFFICIENCY)) + // .map(Enchantment::getLevel).orElse(0); + //int hasteEffectLevel = Optional.ofNullable(player.getEffect(Effect.HASTE)) + // .map(Effect::getAmplifier).orElse(0); + //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 breakTime0(blockHardness, correctTool, canHarvestWithHand, blockId, itemToolType, itemTier, + // efficiencyLoreLevel, hasteEffectLevel, insideOfWaterWithoutAquaAffinity, outOfWaterButNotOnGround); + return breakTime0(blockHardness/*, item.getToolTier()*/); + } + } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 9601b5819..4c1c21581 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -52,7 +52,7 @@ public class Toolbox { public static final CompoundTag BIOMES; public static final ItemData[] CREATIVE_ITEMS; - public static final Collection<StartGamePacket.ItemEntry> ITEMS = new ArrayList<>(); + public static final List<StartGamePacket.ItemEntry> ITEMS = new ArrayList<>(); public static final Int2ObjectMap<ItemEntry> ITEM_ENTRIES = new Int2ObjectOpenHashMap<>(); @@ -103,8 +103,12 @@ public class Toolbox { Iterator<Map.Entry<String, JsonNode>> iterator = items.fields(); while (iterator.hasNext()) { Map.Entry<String, JsonNode> entry = iterator.next(); - ITEM_ENTRIES.put(itemIndex, new ItemEntry(entry.getKey(), itemIndex, - entry.getValue().get("bedrock_id").intValue(), entry.getValue().get("bedrock_data").intValue())); + ITEM_ENTRIES.put(itemIndex, new ItemEntry( + entry.getKey(), itemIndex, + entry.getValue().get("bedrock_id").intValue(), + entry.getValue().get("bedrock_data").intValue()/*, + entry.getValue().get("tool_type").textValue(), + entry.getValue().get("tool_tier").textValue()*/)); itemIndex++; }