From d93d4d0942381046f9c0e7d63060db7b6ff1c557 Mon Sep 17 00:00:00 2001 From: David Choo Date: Mon, 26 Oct 2020 11:54:37 -0400 Subject: [PATCH] Projectile fixes (#1451) * Predict the trajectory of projectiles and add particles * Correct lingering potion gravity * Update last position on move absolute * Clean up * Add egg to ItemRegistry and update mappings --- .../connector/entity/ThrowableEntity.java | 54 +++++++++++++++++++ .../translators/item/ItemRegistry.java | 7 +++ .../entity/JavaEntityStatusTranslator.java | 25 +++++++++ connector/src/main/resources/mappings | 2 +- 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java index d0632d97d..b3632606b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java @@ -26,11 +26,65 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; public class ThrowableEntity extends Entity { + private Vector3f lastPosition; + private ScheduledFuture positionUpdater; + public ThrowableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); + this.lastPosition = position; + } + + @Override + public void spawnEntity(GeyserSession session) { + super.spawnEntity(session); + positionUpdater = session.getConnector().getGeneralThreadPool().scheduleAtFixedRate(() -> { + super.moveRelative(session, motion.getX(), motion.getY(), motion.getZ(), rotation, onGround); + + if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY)) { + float gravity = 0.03f; // Snowball, Egg, and Ender Pearl + if (entityType == EntityType.THROWN_POTION || entityType == EntityType.LINGERING_POTION) { + gravity = 0.05f; + } else if (entityType == EntityType.THROWN_EXP_BOTTLE) { + gravity = 0.07f; + } + motion = motion.down(gravity); + } + }, 0, 50, TimeUnit.MILLISECONDS); + } + + @Override + public boolean despawnEntity(GeyserSession session) { + positionUpdater.cancel(true); + if (entityType == EntityType.THROWN_ENDERPEARL) { + LevelEventPacket particlePacket = new LevelEventPacket(); + particlePacket.setType(LevelEventType.PARTICLE_TELEPORT); + particlePacket.setPosition(position); + session.sendUpstreamPacket(particlePacket); + } + return super.despawnEntity(session); + } + + @Override + public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) { + position = lastPosition; + super.moveRelative(session, relX, relY, relZ, rotation, isOnGround); + lastPosition = position; + } + + @Override + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { + super.moveAbsolute(session, position, rotation, isOnGround, teleported); + lastPosition = position; } } 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 850e4e059..597c87b26 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 @@ -63,6 +63,10 @@ public class ItemRegistry { * Bucket item entry, used in BedrockInventoryTransactionTranslator.java */ public static ItemEntry BUCKET; + /** + * Egg item entry, used in JavaEntityStatusTranslator.java + */ + public static ItemEntry EGG; /** * Gold item entry, used in PiglinEntity.java */ @@ -141,6 +145,9 @@ public class ItemRegistry { case "minecraft:oak_boat": BOAT = ITEM_ENTRIES.get(itemIndex); break; + case "minecraft:egg": + EGG = ITEM_ENTRIES.get(itemIndex); + break; case "minecraft:gold_ingot": GOLD = ITEM_ENTRIES.get(itemIndex); break; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java index c3fbd2e92..09d0eaa91 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java @@ -25,10 +25,16 @@ package org.geysermc.connector.network.translators.java.entity; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.world.particle.ItemParticleData; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityStatusPacket; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityEventType; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import org.geysermc.connector.entity.Entity; @@ -36,6 +42,9 @@ import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; @Translator(packet = ServerEntityStatusPacket.class) public class JavaEntityStatusTranslator extends PacketTranslator { @@ -88,6 +97,22 @@ public class JavaEntityStatusTranslator extends PacketTranslator