diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java
index 075690662..efded1f6f 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/AnimalEntity.java
@@ -28,6 +28,8 @@ package org.geysermc.connector.entity.living.animal;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.living.AgeableEntity;
import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class AnimalEntity extends AgeableEntity {
@@ -40,7 +42,7 @@ public class AnimalEntity extends AgeableEntity {
* wheat
.
* @return true if this is a valid item to breed with for this animal.
*/
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
// This is what it defaults to. OK.
return javaIdentifierStripped.equals("wheat");
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java
index d076b8a6f..b2d5faaad 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java
@@ -26,7 +26,6 @@
package org.geysermc.connector.entity.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
-import com.google.common.collect.ImmutableSet;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
@@ -34,16 +33,9 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
-
-import java.util.Set;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class BeeEntity extends AnimalEntity {
- /**
- * A list of all flowers. Used for feeding bees.
- */
- private static final Set FLOWERS = ImmutableSet.of("dandelion", "poppy", "blue_orchid", "allium", "azure_bluet",
- "red_tulip", "pink_tulip", "white_tulip", "orange_tulip", "cornflower", "lily_of_the_valley", "wither_rose",
- "sunflower", "lilac", "rose_bush", "peony");
public BeeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
@@ -74,7 +66,7 @@ public class BeeEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
- return FLOWERS.contains(javaIdentifierStripped);
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
+ return session.getTagCache().isFlower(itemEntry);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java
index 66e8f9ac8..b5f0395d4 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/ChickenEntity.java
@@ -27,6 +27,8 @@ package org.geysermc.connector.entity.living.animal;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class ChickenEntity extends AnimalEntity {
@@ -35,7 +37,7 @@ public class ChickenEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.contains("seeds");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java
index bfa376272..ff71e87f0 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java
@@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class FoxEntity extends AnimalEntity {
@@ -54,7 +55,7 @@ public class FoxEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("sweet_berries");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java
index b915c07de..9fbb17725 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java
@@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.utils.DimensionUtils;
public class HoglinEntity extends AnimalEntity {
@@ -49,7 +50,7 @@ public class HoglinEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("crimson_fungus");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java
index 7c7d74770..1cf541c8c 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java
@@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class OcelotEntity extends AnimalEntity {
@@ -46,7 +47,7 @@ public class OcelotEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java
index 9431d66a0..2f5ced080 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java
@@ -33,6 +33,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
public class PandaEntity extends AnimalEntity {
@@ -80,7 +81,7 @@ public class PandaEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("bamboo");
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java
index 551e1c345..bbb1aed20 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java
@@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class PigEntity extends AnimalEntity {
@@ -47,7 +48,7 @@ public class PigEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot");
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java
index 7b5d42f35..f33635aeb 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java
@@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class PolarBearEntity extends AnimalEntity {
@@ -46,7 +47,7 @@ public class PolarBearEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return false;
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java
index a789b48e4..9137cd23a 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java
@@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class RabbitEntity extends AnimalEntity {
@@ -61,7 +62,7 @@ public class RabbitEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot");
}
}
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java
index 2a99a5a03..a90a044bc 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java
@@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class StriderEntity extends AnimalEntity {
@@ -87,7 +88,7 @@ public class StriderEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("warped_fungus");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java
index 89df815d7..536f40755 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java
@@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class TurtleEntity extends AnimalEntity {
@@ -48,7 +49,7 @@ public class TurtleEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("seagrass");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java
index d2f89e101..324c8229f 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java
@@ -37,6 +37,7 @@ import org.geysermc.connector.entity.attribute.AttributeType;
import org.geysermc.connector.entity.living.animal.AnimalEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
import java.util.Set;
@@ -112,7 +113,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java
index 0b21c771e..8ab1df1a8 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java
@@ -32,6 +32,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
public class LlamaEntity extends ChestedHorseEntity {
@@ -77,7 +78,7 @@ public class LlamaEntity extends ChestedHorseEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java
index 7866d25cf..2d56d0c18 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java
@@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class CatEntity extends TameableEntity {
@@ -85,7 +86,7 @@ public class CatEntity extends TameableEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java
index 50ec9ed04..45327c785 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java
@@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
public class ParrotEntity extends TameableEntity {
@@ -47,7 +48,7 @@ public class ParrotEntity extends TameableEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.contains("seeds") || javaIdentifierStripped.equals("cookie");
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java
index 91350ef54..bb7916937 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java
@@ -32,6 +32,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import java.util.Set;
@@ -87,7 +88,7 @@ public class WolfEntity extends TameableEntity {
}
@Override
- public boolean canEat(String javaIdentifierStripped) {
+ public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
// Cannot be a baby to eat these foods
return WOLF_FOODS.contains(javaIdentifierStripped) && !metadata.getFlags().getFlag(EntityFlag.BABY);
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java
index e6e509b11..44fa2c49d 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java
@@ -61,7 +61,7 @@ public class PiglinEntity extends BasePiglinEntity {
@Override
public void updateOffHand(GeyserSession session) {
// Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates
- boolean changed = metadata.getFlags().setFlag(EntityFlag.ADMIRING, offHand.getId() == ItemRegistry.GOLD.getBedrockId());
+ boolean changed = metadata.getFlags().setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(ItemRegistry.getItem(this.offHand)));
if (changed) {
super.updateBedrockMetadata(session);
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
index 63cdc6ece..081ad859a 100644
--- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
+++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
@@ -146,6 +146,7 @@ public class GeyserSession implements CommandSender {
private ChunkCache chunkCache;
private EntityCache entityCache;
private EntityEffectCache effectCache;
+ private final TagCache tagCache;
private WorldCache worldCache;
private WindowCache windowCache;
private final Int2ObjectMap teleportMap = new Int2ObjectOpenHashMap<>();
@@ -452,6 +453,7 @@ public class GeyserSession implements CommandSender {
this.chunkCache = new ChunkCache(this);
this.entityCache = new EntityCache(this);
this.effectCache = new EntityEffectCache();
+ this.tagCache = new TagCache();
this.worldCache = new WorldCache(this);
this.windowCache = new WindowCache(this);
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java
new file mode 100644
index 000000000..c46e37b74
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/TagCache.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.network.session.cache;
+
+import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareTagsPacket;
+import it.unimi.dsi.fastutil.ints.IntList;
+import it.unimi.dsi.fastutil.ints.IntLists;
+import org.geysermc.connector.network.translators.item.ItemEntry;
+import org.geysermc.connector.registry.type.BlockMapping;
+
+import java.util.Map;
+
+/**
+ * Manages information sent from the {@link ServerDeclareTagsPacket}. If that packet is not sent, all lists here
+ * will remain empty, matching Java Edition behavior.
+ */
+public class TagCache {
+ /* Blocks */
+ private IntList wool = IntLists.emptyList();
+ /* Items */
+ private IntList flowers = IntLists.emptyList();
+ private IntList piglinLoved = IntLists.emptyList();
+
+ public void loadPacket(ServerDeclareTagsPacket packet) {
+ Map blockTags = packet.getBlockTags();
+ this.wool = IntList.of(blockTags.get("minecraft:wool"));
+
+ Map itemTags = packet.getItemTags();
+ this.flowers = IntList.of(itemTags.get("minecraft:flowers"));
+ this.piglinLoved = IntList.of(itemTags.get("minecraft:piglin_loved"));
+ }
+
+ public void clear() {
+ this.wool = IntLists.emptyList();
+
+ this.flowers = IntLists.emptyList();
+ this.piglinLoved = IntLists.emptyList();
+ }
+
+ public boolean isFlower(ItemEntry itemEntry) {
+ return flowers.contains(itemEntry.getJavaId());
+ }
+
+ public boolean shouldPiglinAdmire(ItemEntry itemEntry) {
+ return piglinLoved.contains(itemEntry.getJavaId());
+ }
+
+ public boolean isWool(BlockMapping blockMapping) {
+ return wool.contains(blockMapping.getJavaBlockId());
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
index 9becfb36f..350c029ff 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
@@ -46,6 +46,6 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator type : collisionTypes) {
CollisionRemapper annotation = annotationMap.get(type);
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
index 10c14074f..0e1a28d54 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
@@ -108,10 +108,6 @@ public class ItemRegistry {
* Egg item entry, used in JavaEntityStatusTranslator.java
*/
public static ItemEntry EGG;
- /**
- * Gold item entry, used in PiglinEntity.java
- */
- public static ItemEntry GOLD;
/**
* Shield item entry, used in Entity.java and LivingEntity.java
*/
@@ -294,7 +290,7 @@ public class ItemRegistry {
// However, in order for some visuals and crafting to work, we need to send the first matching block state
// as indexed by Bedrock's block palette
// There are exceptions! But, ideally, the block ID override should take care of those.
- String javaBlockIdentifier = BlockTranslator.getJavaIdBlockMap().inverse().get(blockRuntimeIdNode.intValue()).split("\\[")[0];
+ String javaBlockIdentifier = BlockTranslator.getBlockMapping(blockRuntimeIdNode.intValue()).getCleanJavaIdentifier();
NbtMapBuilder requiredBlockStatesBuilder = NbtMap.builder();
String correctBedrockIdentifier = blockTranslator.getAllBedrockBlockStates().get(aValidBedrockBlockId).getString("name");
boolean firstPass = true;
@@ -437,9 +433,6 @@ public class ItemRegistry {
case "minecraft:egg":
EGG = itemEntry;
break;
- case "minecraft:gold_ingot":
- GOLD = itemEntry;
- break;
case "minecraft:shield":
SHIELD = itemEntry;
break;
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java
new file mode 100644
index 000000000..368693bf2
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareTagsTranslator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.network.translators.java;
+
+import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareTagsPacket;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.PacketTranslator;
+import org.geysermc.connector.network.translators.Translator;
+
+@Translator(packet = ServerDeclareTagsPacket.class)
+public class JavaDeclareTagsTranslator extends PacketTranslator {
+
+ @Override
+ public void translate(ServerDeclareTagsPacket packet, GeyserSession session) {
+ session.getTagCache().loadPacket(packet);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
index abd79437f..47918440b 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
@@ -63,6 +63,8 @@ public class JavaJoinGameTranslator extends PacketTranslator itemFrames = new Object2IntOpenHashMap<>();
private final Map flowerPotBlocks = new HashMap<>();
- public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap();
- public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap();
- public static final Int2ObjectMap JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>();
-
- // The index of the collision data in collision.json
- public static final Int2IntMap JAVA_RUNTIME_ID_TO_COLLISION_INDEX = new Int2IntOpenHashMap();
-
- private static final Int2ObjectMap JAVA_RUNTIME_ID_TO_PICK_ITEM = new Int2ObjectOpenHashMap<>();
+ private static final Int2ObjectMap JAVA_RUNTIME_ID_TO_BLOCK_MAPPING = new Int2ObjectOpenHashMap<>();
/**
* Java numeric ID to java unique identifier, used for block names in the statistics screen
@@ -96,11 +90,7 @@ public abstract class BlockTranslator {
private final EmptyChunkProvider emptyChunkProvider;
- /**
- * A list of all Java runtime wool IDs, for use with block breaking math and shears
- */
- public static final IntSet JAVA_RUNTIME_WOOL_IDS = new IntOpenHashSet();
- public static final int JAVA_RUNTIME_COBWEB_ID;
+ public static final int JAVA_COBWEB_BLOCK_ID;
public static final int JAVA_RUNTIME_FURNACE_ID;
public static final int JAVA_RUNTIME_FURNACE_LIT_ID;
@@ -127,7 +117,7 @@ public abstract class BlockTranslator {
}
int javaRuntimeId = -1;
- int cobwebRuntimeId = -1;
+ int cobwebBlockId = -1;
int furnaceRuntimeId = -1;
int furnaceLitRuntimeId = -1;
int spawnerRuntimeId = -1;
@@ -139,31 +129,35 @@ public abstract class BlockTranslator {
Map.Entry entry = blocksIterator.next();
String javaId = entry.getKey();
+ BlockMapping.BlockMappingBuilder builder = BlockMapping.builder();
// 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.doubleValue());
+ builder.hardness(hardnessNode.doubleValue());
}
- try {
- JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue());
- } catch (Exception e) {
- JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, false);
+ JsonNode canBreakWithHandNode = entry.getValue().get("can_break_with_hand");
+ if (canBreakWithHandNode != null) {
+ builder.canBreakWithHand(canBreakWithHandNode.booleanValue());
+ } else {
+ builder.canBreakWithHand(false);
}
JsonNode toolTypeNode = entry.getValue().get("tool_type");
if (toolTypeNode != null) {
- JAVA_RUNTIME_ID_TO_TOOL_TYPE.put(javaRuntimeId, toolTypeNode.textValue());
+ builder.toolType(toolTypeNode.textValue());
+ } else {
+ builder.toolType("");
}
JsonNode collisionIndexNode = entry.getValue().get("collision_index");
if (hardnessNode != null) {
- JAVA_RUNTIME_ID_TO_COLLISION_INDEX.put(javaRuntimeId, collisionIndexNode.intValue());
+ builder.collisionIndex(collisionIndexNode.intValue());
}
JsonNode pickItemNode = entry.getValue().get("pick_item");
if (pickItemNode != null) {
- JAVA_RUNTIME_ID_TO_PICK_ITEM.put(javaRuntimeId, pickItemNode.textValue());
+ builder.pickItem(pickItemNode.textValue());
}
JAVA_ID_BLOCK_MAP.put(javaId, javaRuntimeId);
@@ -183,11 +177,14 @@ public abstract class BlockTranslator {
JAVA_TO_BEDROCK_IDENTIFIERS.put(cleanJavaIdentifier, bedrockIdentifier);
}
- if (javaId.contains("wool")) {
- JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId);
+ builder.javaBlockId(uniqueJavaId);
- } else if (javaId.contains("cobweb")) {
- cobwebRuntimeId = javaRuntimeId;
+ builder.javaIdentifier(javaId);
+
+ JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.put(javaRuntimeId, builder.build());
+
+ if (javaId.contains("cobweb")) {
+ cobwebBlockId = uniqueJavaId;
} else if (javaId.startsWith("minecraft:furnace[facing=north")) {
if (javaId.contains("lit=true")) {
@@ -204,10 +201,10 @@ public abstract class BlockTranslator {
}
}
- if (cobwebRuntimeId == -1) {
+ if (cobwebBlockId == -1) {
throw new AssertionError("Unable to find cobwebs in palette");
}
- JAVA_RUNTIME_COBWEB_ID = cobwebRuntimeId;
+ JAVA_COBWEB_BLOCK_ID = cobwebBlockId;
if (furnaceRuntimeId == -1) {
throw new AssertionError("Unable to find furnace in palette");
@@ -229,6 +226,8 @@ public abstract class BlockTranslator {
}
JAVA_WATER_ID = waterRuntimeId;
+ BlockMapping.AIR = JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.get(JAVA_AIR_ID);
+
BlockTranslator1_16_100.init();
BlockTranslator1_16_210.init();
BLOCKS_JSON = null; // We no longer require this so let it garbage collect away
@@ -457,18 +456,11 @@ public abstract class BlockTranslator {
}
/**
- * Get the item a Java client would receive when pressing
- * the Pick Block key on a specific Java block state.
- *
- * @param javaId The Java runtime id of the block
- * @return The Java identifier of the item
+ * @param javaRuntimeId the Java runtime ID of the block to search for.
+ * @return the corresponding block mapping for this runtime ID.
*/
- public static String getPickItem(int javaId) {
- String itemIdentifier = JAVA_RUNTIME_ID_TO_PICK_ITEM.get(javaId);
- if (itemIdentifier == null) {
- return JAVA_ID_BLOCK_MAP.inverse().get(javaId).split("\\[")[0];
- }
- return itemIdentifier;
+ public static BlockMapping getBlockMapping(int javaRuntimeId) {
+ return JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.getOrDefault(javaRuntimeId, BlockMapping.AIR);
}
/**
diff --git a/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java b/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java
new file mode 100644
index 000000000..8aa06abc2
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/registry/type/BlockMapping.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @author GeyserMC
+ * @link https://github.com/GeyserMC/Geyser
+ */
+
+package org.geysermc.connector.registry.type;
+
+import lombok.Builder;
+import lombok.Value;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+@Builder
+@Value
+public class BlockMapping {
+ public static BlockMapping AIR;
+
+ String javaIdentifier;
+ /**
+ * The block ID shared between all different block states of this block.
+ * NOT the runtime ID!
+ */
+ int javaBlockId;
+
+ double hardness;
+ boolean canBreakWithHand;
+ @Nonnull String toolType;
+ /**
+ * The index of this collision in collision.json
+ */
+ int collisionIndex;
+ @Nullable String pickItem;
+
+ /**
+ * @return the identifier without the additional block states
+ */
+ public String getCleanJavaIdentifier() {
+ return javaIdentifier.split("\\[")[0];
+ }
+
+ /**
+ * Get the item a Java client would receive when pressing
+ * the Pick Block key on a specific Java block state.
+ *
+ * @return The Java identifier of the item
+ */
+ public String getPickItem() {
+ if (pickItem != null) {
+ return pickItem;
+ }
+
+ return getCleanJavaIdentifier();
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java
index 997e4aee4..01c85ab43 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java
@@ -33,6 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ToolItemEntry;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
+import org.geysermc.connector.registry.type.BlockMapping;
public class BlockUtils {
/**
@@ -108,11 +109,11 @@ public class BlockUtils {
return 1.0 / speed;
}
- 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, "");
- boolean canHarvestWithHand = BlockTranslator.JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.get(blockId);
+ public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemEntry item, CompoundTag nbtData, boolean isSessionPlayer) {
+ boolean isWoolBlock = session.getTagCache().isWool(blockMapping);
+ boolean isCobweb = blockMapping.getJavaBlockId() == BlockTranslator.JAVA_COBWEB_BLOCK_ID;
+ String blockToolType = blockMapping.getToolType();
+ boolean canHarvestWithHand = blockMapping.isCanBreakWithHand();
String toolType = "";
String toolTier = "";
boolean correctTool = false;
@@ -126,8 +127,11 @@ public class BlockUtils {
int hasteLevel = 0;
int miningFatigueLevel = 0;
- if (session == null) {
- return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, false, false);
+ if (!isSessionPlayer) {
+ // Another entity is currently mining; we have all the information we know
+ return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock,
+ isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false,
+ false, false);
}
hasteLevel = session.getEffectCache().getEffectLevel(Effect.FASTER_DIG);
@@ -140,7 +144,9 @@ public class BlockUtils {
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);
+ return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock,
+ isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity,
+ outOfWaterButNotOnGround, insideWaterNotOnGround);
}
/**
diff --git a/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java b/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java
index ff7ad11cf..1d6cf60d9 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/InteractiveTagManager.java
@@ -82,7 +82,7 @@ public class InteractiveTagManager {
// Holding a leash and the mob is leashable for sure
// (Plugins can change this behavior so that's something to look into in the far far future)
interactiveTag = InteractiveTag.LEASH;
- } else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(javaIdentifierStripped)) {
+ } else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(session, javaIdentifierStripped, itemEntry)) {
// This animal can be fed
interactiveTag = InteractiveTag.FEED;
} else {