diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/types/CosmeticBalloonType.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/types/CosmeticBalloonType.java index 94789055..c8dd11fa 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/types/CosmeticBalloonType.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/cosmetic/types/CosmeticBalloonType.java @@ -2,11 +2,13 @@ package com.hibiscusmc.hmccosmetics.cosmetic.types; import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.cosmetic.Cosmetic; +import com.hibiscusmc.hmccosmetics.entities.BalloonEntity; import com.hibiscusmc.hmccosmetics.user.CosmeticUser; import com.hibiscusmc.hmccosmetics.util.PlayerUtils; import com.hibiscusmc.hmccosmetics.util.packets.PacketManager; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.spongepowered.configurate.ConfigurationNode; @@ -26,21 +28,28 @@ public class CosmeticBalloonType extends Cosmetic { @Override public void update(CosmeticUser user) { Player player = Bukkit.getPlayer(user.getUniqueId()); + Location currentLocation = user.getBalloonEntity().getLocation().clone(); + Location newLocation = player.getLocation().clone().add(Settings.getBalloonOffset()).clone(); if (player == null) return; if (user.isInWardrobe()) return; - final Location actual = player.getLocation().clone().add(Settings.getBalloonOffset()); - - if (player.getLocation().getWorld() != user.getBalloonEntity().getLocation().getWorld()) { - user.getBalloonEntity().getModelEntity().teleport(actual); - } - - user.getBalloonEntity().getModelEntity().teleport(actual); - List viewer = PlayerUtils.getNearbyPlayers(player); viewer.add(player); - PacketManager.sendTeleportPacket(user.getBalloonEntity().getPufferfishBalloonId(), actual, false, viewer); + BalloonEntity balloonEntity = user.getBalloonEntity(); + + if (player.getLocation().getWorld() != balloonEntity.getLocation().getWorld()) { + balloonEntity.getModelEntity().teleport(newLocation); + PacketManager.sendTeleportPacket(balloonEntity.getPufferfishBalloonId(), newLocation, false, viewer); + return; + } + + newLocation.add(player.getVelocity().clone().multiply(-1)); + balloonEntity.setLocation(newLocation); + balloonEntity.setVelocity(newLocation.clone().subtract(currentLocation.clone()).toVector()); + + PacketManager.sendTeleportPacket(balloonEntity.getPufferfishBalloonId(), newLocation, false, viewer); + PacketManager.sendLeashPacket(balloonEntity.getPufferfishBalloonId(), player.getEntityId(), viewer); } public String getModelName() { diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/entities/BalloonEntity.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/entities/BalloonEntity.java index 22b84c44..a1bc62a2 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/entities/BalloonEntity.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/entities/BalloonEntity.java @@ -3,6 +3,7 @@ package com.hibiscusmc.hmccosmetics.entities; import com.hibiscusmc.hmccosmetics.config.Settings; import com.hibiscusmc.hmccosmetics.nms.NMSHandlers; import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import com.hibiscusmc.hmccosmetics.util.packets.PacketManager; import com.ticxo.modelengine.api.ModelEngineAPI; import com.ticxo.modelengine.api.model.ActiveModel; import com.ticxo.modelengine.api.model.ModeledEntity; @@ -21,6 +22,7 @@ public class BalloonEntity { private final int balloonID; private final UUID uniqueID; private final Entity modelEntity; + private ModeledEntity modeledEntity; public BalloonEntity(Location location) { this.uniqueID = UUID.randomUUID(); @@ -42,6 +44,7 @@ public class BalloonEntity { singleModel.getRendererHandler().setColor(color); }); } + this.modeledEntity = modeledEntity; } public void remove() { @@ -108,7 +111,6 @@ public class BalloonEntity { public void setLocation(Location location) { //this.megEntity.teleportTo(location.getX(), location.getY(), location.getZ()); - location = location.add(Settings.getBalloonOffset()); this.modelEntity.teleport(location); } diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/listener/PlayerGameListener.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/listener/PlayerGameListener.java index 9375acc2..360a6370 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/listener/PlayerGameListener.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/listener/PlayerGameListener.java @@ -104,8 +104,6 @@ public class PlayerGameListener implements Listener { if (event.getCause().equals(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) || event.getCause().equals(PlayerTeleportEvent.TeleportCause.END_PORTAL)) return; if (user.hasCosmeticInSlot(CosmeticSlot.BALLOON)) { - user.getBalloonEntity().setLocation(event.getTo()); - Bukkit.getScheduler().runTaskLater(HMCCosmeticsPlugin.getInstance(), () -> { user.updateCosmetic(CosmeticSlot.BALLOON); }, 2); diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/PacketManager.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/PacketManager.java index 331042a6..d5034cae 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/PacketManager.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/PacketManager.java @@ -12,6 +12,7 @@ import com.hibiscusmc.hmccosmetics.util.MessagesUtil; import com.hibiscusmc.hmccosmetics.util.PlayerUtils; import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerNamedEntitySpawn; import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerPlayerInfo; +import com.hibiscusmc.hmccosmetics.util.packets.wrappers.WrapperPlayServerRelEntityMove; import it.unimi.dsi.fastutil.ints.IntArrayList; import org.bukkit.Location; import org.bukkit.World; @@ -342,6 +343,14 @@ public class PacketManager extends BasePacket { for (final Player p : sendTo) sendPacket(p, info.getHandle()); } + public static void sendLeashPacket( + final int leashedEntity, + final int entityId, + final Location location + ) { + sendLeashPacket(leashedEntity, entityId, getViewers(location)); + } + /** * Sends a leash packet, useful for balloons! * @param leashedEntity Entity being leashed (ex. a horse) @@ -353,10 +362,10 @@ public class PacketManager extends BasePacket { final int entityId, final List sendTo ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY); + packet.getIntegers().write(0, leashedEntity); + packet.getIntegers().write(1, entityId); for (final Player p : sendTo) { - PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY); - packet.getIntegers().write(0, leashedEntity); - packet.getIntegers().write(1, entityId); sendPacket(p, packet); } } @@ -387,6 +396,42 @@ public class PacketManager extends BasePacket { } } + /** + * Sends a movement packet from one location to another + * @param entityId Entity this will affect + * @param from Previous location + * @param to New location + * @param onGround If the movement is on the ground + * @param sendTo Whom to send the packet to + */ + public static void sendMovePacket( + final int entityId, + final Location from, + final Location to, + final boolean onGround, + List sendTo + ) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE); + WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet); + wrapper.setEntityID(entityId); + wrapper.setDx(to.getX() - from.getX()); + wrapper.setDy(to.getY() - from.getY()); + wrapper.setDz(to.getZ() - from.getZ()); + wrapper.setOnGround(onGround); + for (final Player p : sendTo) { + sendPacket(p, wrapper.getHandle()); + } + } + + public static void sendMovePacket( + final int entityId, + final Location from, + final Location to, + final boolean onGround + ) { + sendMovePacket(entityId, from, to, onGround, getViewers(to)); + } + private static List getViewers(Location location) { ArrayList viewers = new ArrayList(); if (Settings.getViewDistance() <= 0) { diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/wrappers/WrapperPlayServerRelEntityMove.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/wrappers/WrapperPlayServerRelEntityMove.java new file mode 100644 index 00000000..a778e03f --- /dev/null +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/util/packets/wrappers/WrapperPlayServerRelEntityMove.java @@ -0,0 +1,169 @@ +package com.hibiscusmc.hmccosmetics.util.packets.wrappers; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import org.bukkit.World; +import org.bukkit.entity.Entity; + +public class WrapperPlayServerRelEntityMove extends AbstractPacket { + public static final PacketType TYPE = + PacketType.Play.Server.REL_ENTITY_MOVE; + + public WrapperPlayServerRelEntityMove() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerRelEntityMove(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve Entity ID. + *

+ * Notes: entity's ID + * + * @return The current Entity ID + */ + public int getEntityID() { + return handle.getIntegers().read(0); + } + + /** + * Set Entity ID. + * + * @param value - new value. + */ + public void setEntityID(int value) { + handle.getIntegers().write(0, value); + } + + /** + * Retrieve the entity of the painting that will be spawned. + * + * @param world - the current world of the entity. + * @return The spawned entity. + */ + public Entity getEntity(World world) { + return handle.getEntityModifier(world).read(0); + } + + /** + * Retrieve the entity of the painting that will be spawned. + * + * @param event - the packet event. + * @return The spawned entity. + */ + public Entity getEntity(PacketEvent event) { + return getEntity(event.getPlayer().getWorld()); + } + + /** + * Retrieve DX. + * + * @return The current DX + */ + public double getDx() { + return handle.getShorts().read(0) / 4096D; + } + + /** + * Set DX. + * + * @param value - new value. + */ + public void setDx(double value) { + handle.getShorts().write(0, (short) (value * 4096)); + } + + /** + * Retrieve DY. + * + * @return The current DY + */ + public double getDy() { + return handle.getShorts().read(1) / 4096D; + } + + /** + * Set DY. + * + * @param value - new value. + */ + public void setDy(double value) { + handle.getShorts().write(1, (short) (value * 4096)); + } + + /** + * Retrieve DZ. + * + * @return The current DZ + */ + public double getDz() { + return handle.getShorts().read(2) / 4096D; + } + + /** + * Set DZ. + * + * @param value - new value. + */ + public void setDz(double value) { + handle.getShorts().write(2, (short) (value * 4096)); + } + + /** + * Retrieve the yaw of the current entity. + * + * @return The current Yaw + */ + public float getYaw() { + return (handle.getBytes().read(0) * 360.F) / 256.0F; + } + + /** + * Set the yaw of the current entity. + * + * @param value - new yaw. + */ + public void setYaw(float value) { + handle.getBytes().write(0, (byte) (value * 256.0F / 360.0F)); + } + + /** + * Retrieve the pitch of the current entity. + * + * @return The current pitch + */ + public float getPitch() { + return (handle.getBytes().read(1) * 360.F) / 256.0F; + } + + /** + * Set the pitch of the current entity. + * + * @param value - new pitch. + */ + public void setPitch(float value) { + handle.getBytes().write(1, (byte) (value * 256.0F / 360.0F)); + } + + /** + * Retrieve On Ground. + * + * @return The current On Ground + */ + public boolean getOnGround() { + return handle.getBooleans().read(0); + } + + /** + * Set On Ground. + * + * @param value - new value. + */ + public void setOnGround(boolean value) { + handle.getBooleans().write(0, value); + } +} \ No newline at end of file