diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleProperties.java similarity index 94% rename from plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java rename to plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleProperties.java index ff53417..4e4605a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/ArmorStandVehicleProperties.java @@ -16,11 +16,11 @@ import java.util.Set; * This entity is used to make the NPC sit on an invisible armor stand. *

*/ -public class ArmorStandVehicleEntity implements PropertyHolder { +public class ArmorStandVehicleProperties implements PropertyHolder { private final Map, Object> propertyMap = new HashMap<>(); - public ArmorStandVehicleEntity(EntityPropertyRegistryImpl propertyRegistry) { + public ArmorStandVehicleProperties(EntityPropertyRegistryImpl propertyRegistry) { _setProperty(propertyRegistry.getByName("small", Boolean.class), true); _setProperty(propertyRegistry.getByName("invisible", Boolean.class), true); _setProperty(propertyRegistry.getByName("base_plate", Boolean.class), false); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java index 5687adc..255a201 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/PacketEntity.java @@ -4,17 +4,15 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import lol.pyr.znpcsplus.ZNpcsPlusBootstrap; import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.reflection.Reflections; import lol.pyr.znpcsplus.util.NpcLocation; +import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.Collection; -import java.util.HashMap; import java.util.Set; import java.util.UUID; @@ -22,17 +20,19 @@ public class PacketEntity implements PropertyHolder { private final PacketFactory packetFactory; private final PropertyHolder properties; + private final Viewable viewable; private final int entityId; private final UUID uuid; private final EntityType type; private NpcLocation location; - private final HashMap metadata = new HashMap<>(); + private PacketEntity vehicle; - public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, EntityType type, NpcLocation location) { + public PacketEntity(PacketFactory packetFactory, PropertyHolder properties, Viewable viewable, EntityType type, NpcLocation location) { this.packetFactory = packetFactory; this.properties = properties; + this.viewable = viewable; this.entityId = reserveEntityID(); this.uuid = UUID.randomUUID(); this.type = type; @@ -55,31 +55,59 @@ public class PacketEntity implements PropertyHolder { return type; } - public void setLocation(NpcLocation location, Collection viewers) { + public void setLocation(NpcLocation location) { this.location = location; - for (Player viewer : viewers) packetFactory.teleportEntity(viewer, this); + if (vehicle != null) { + vehicle.setLocation(location.withY(location.getY() - 0.9)); + return; + } + for (Player viewer : viewable.getViewers()) packetFactory.teleportEntity(viewer, this); } public void spawn(Player player) { if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties); else packetFactory.spawnEntity(player, this, properties); + if (vehicle != null) { + vehicle.spawn(player); + packetFactory.setPassenger(player, vehicle, this); + } } public void setHeadRotation(Player player, float yaw, float pitch) { packetFactory.sendHeadRotation(player, this, yaw, pitch); } - public void despawn(Player player) { - packetFactory.destroyEntity(player, this, properties); - if (hasMetadata("ridingVehicle")) { - try { - PacketEntity armorStand = (PacketEntity) getMetadata("ridingVehicle"); - armorStand.despawn(player); - } catch (Exception e) { - //noinspection CallToPrintStackTrace - e.printStackTrace(); + public PacketEntity getVehicle() { + return vehicle; + } + + public Viewable getViewable() { + return viewable; + } + + public void setVehicle(PacketEntity vehicle) { + // remove old vehicle + if (this.vehicle != null) { + for (Player player : viewable.getViewers()) { + packetFactory.setPassenger(player, this.vehicle, null); + this.vehicle.despawn(player); + packetFactory.teleportEntity(player, this); } } + + this.vehicle = vehicle; + if (this.vehicle == null) return; + + vehicle.setLocation(location.withY(location.getY() - 0.9)); + for (Player player : viewable.getViewers()) { + vehicle.spawn(player); + packetFactory.setPassenger(player, vehicle, this); + } + } + + public void despawn(Player player) { + packetFactory.destroyEntity(player, this, properties); + if (vehicle != null) vehicle.despawn(player); } public void refreshMeta(Player player) { @@ -129,32 +157,4 @@ public class PacketEntity implements PropertyHolder { public Set> getAppliedProperties() { return properties.getAppliedProperties(); } - - public void setMetadata(String key, Object value) { - metadata.put(key, value); - } - - public Object getMetadata(String key) { - return metadata.get(key); - } - - public T getMetadata(String key, Class type) { - try { - return type.cast(metadata.get(key)); - } catch (ClassCastException e) { - return null; - } - } - - public void removeMetadata(String key) { - metadata.remove(key); - } - - public boolean hasMetadata(String key) { - return metadata.containsKey(key); - } - - public void clearMetadata() { - metadata.clear(); - } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java index fb8fc2c..e9b66c5 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java @@ -1,10 +1,8 @@ package lol.pyr.znpcsplus.entity.properties; -import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers; -import lol.pyr.znpcsplus.entity.ArmorStandVehicleEntity; +import lol.pyr.znpcsplus.entity.ArmorStandVehicleProperties; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.entity.PacketEntity; @@ -26,28 +24,12 @@ public class EntitySittingProperty extends EntityPropertyImpl { @Override public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { boolean sitting = entity.getProperty(this); - if (sitting) { - ArmorStandVehicleEntity vehicleEntity = new ArmorStandVehicleEntity(propertyRegistry); - PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, vehicleEntity, EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); - vehiclePacketEntity.spawn(player); - entity.setMetadata("ridingVehicle", vehiclePacketEntity); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSetPassengers( - vehiclePacketEntity.getEntityId(), - new int[]{entity.getEntityId()} - )); - } else { - if (entity.hasMetadata("ridingVehicle")) { - PacketEntity vehicleEntity = (PacketEntity) entity.getMetadata("ridingVehicle"); - PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSetPassengers( - vehicleEntity.getEntityId(), - new int[]{} - )); - vehicleEntity.despawn(player); - entity.removeMetadata("ridingVehicle"); - // Send a packet to reset the npc's position - packetFactory.teleportEntity(player, entity); - } + if (sitting) if (entity.getVehicle() == null) { + PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, new ArmorStandVehicleProperties(propertyRegistry), + entity.getViewable(), EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); + entity.setVehicle(vehiclePacketEntity); + } else if (entity.getVehicle() != null) { + entity.setVehicle(null); } } - } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java index 4092e92..c1a4556 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramImpl.java @@ -38,9 +38,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void addTextLineComponent(Component line) { - HologramText newLine = new HologramText(propertyRegistry, packetFactory, null, line); + HologramText newLine = new HologramText(this, propertyRegistry, packetFactory, null, line); lines.add(newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -57,9 +57,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void addItemLinePEStack(ItemStack item) { - HologramItem newLine = new HologramItem(propertyRegistry, packetFactory, null, item); + HologramItem newLine = new HologramItem(this, propertyRegistry, packetFactory, null, item); lines.add(newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -99,9 +99,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void insertTextLineComponent(int index, Component line) { - HologramText newLine = new HologramText(propertyRegistry, packetFactory, null, line); + HologramText newLine = new HologramText(this, propertyRegistry, packetFactory, null, line); lines.add(index, newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -114,9 +114,9 @@ public class HologramImpl extends Viewable implements Hologram { } public void insertItemLinePEStack(int index, ItemStack item) { - HologramItem newLine = new HologramItem(propertyRegistry, packetFactory, null, item); + HologramItem newLine = new HologramItem(this, propertyRegistry, packetFactory, null, item); lines.add(index, newLine); - relocateLines(newLine); + relocateLines(); for (Player viewer : getViewers()) newLine.show(viewer.getPlayer()); } @@ -172,14 +172,10 @@ public class HologramImpl extends Viewable implements Hologram { } private void relocateLines() { - relocateLines(null); - } - - private void relocateLines(HologramLine newLine) { final double lineSpacing = configManager.getConfig().lineSpacing(); double height = location.getY() + (lines.size() - 1) * lineSpacing + getOffset(); for (HologramLine line : lines) { - line.setLocation(location.withY(height), line == newLine ? Collections.emptySet() : getViewers()); + line.setLocation(location.withY(height)); height -= lineSpacing; } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java index c25e434..da17da4 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramItem.java @@ -15,13 +15,11 @@ import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.util.NpcLocation; -import org.bukkit.entity.Player; - -import java.util.Collection; +import lol.pyr.znpcsplus.util.Viewable; public class HologramItem extends HologramLine { - public HologramItem(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, ItemStack item) { - super(item, packetFactory, EntityTypes.ITEM, location); + public HologramItem(Viewable viewable, EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, ItemStack item) { + super(viewable, item, packetFactory, EntityTypes.ITEM, location); addProperty(propertyRegistry.getByName("holo_item")); } @@ -33,8 +31,8 @@ public class HologramItem extends HologramLine { } @Override - public void setLocation(NpcLocation location, Collection viewers) { - super.setLocation(location.withY(location.getY() + 2.05), viewers); + public void setLocation(NpcLocation location) { + super.setLocation(location.withY(location.getY() + 2.05)); } public static boolean ensureValidItemInput(String in) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java index 3b572e5..79e45c1 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramLine.java @@ -7,10 +7,10 @@ import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.entity.PacketEntity; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.util.NpcLocation; +import lol.pyr.znpcsplus.util.Viewable; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -19,9 +19,9 @@ public class HologramLine implements PropertyHolder { private final PacketEntity entity; private final Set> properties; - public HologramLine(M value, PacketFactory packetFactory, EntityType type, NpcLocation location) { + public HologramLine(Viewable viewable, M value, PacketFactory packetFactory, EntityType type, NpcLocation location) { this.value = value; - this.entity = new PacketEntity(packetFactory, this, type, location); + this.entity = new PacketEntity(packetFactory, this, viewable, type, location); this.properties = new HashSet<>(); } @@ -45,8 +45,8 @@ public class HologramLine implements PropertyHolder { entity.despawn(player); } - public void setLocation(NpcLocation location, Collection viewers) { - entity.setLocation(location, viewers); + public void setLocation(NpcLocation location) { + entity.setLocation(location); } public int getEntityId() { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java index 47e5e91..40c8995 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java @@ -5,6 +5,7 @@ import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.util.NpcLocation; +import lol.pyr.znpcsplus.util.Viewable; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @@ -12,8 +13,8 @@ public class HologramText extends HologramLine { private static final Component BLANK = Component.text("%blank%"); - public HologramText(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) { - super(text, packetFactory, EntityTypes.ARMOR_STAND, location); + public HologramText(Viewable viewable, EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) { + super(viewable, text, packetFactory, EntityTypes.ARMOR_STAND, location); addProperty(propertyRegistry.getByName("name")); addProperty(propertyRegistry.getByName("invisible")); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java index 0a5695a..e29948a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcImpl.java @@ -48,14 +48,14 @@ public class NpcImpl extends Viewable implements Npc { this.type = type; this.location = location; this.uuid = uuid; - entity = new PacketEntity(packetFactory, this, type.getType(), location); + entity = new PacketEntity(packetFactory, this, this, type.getType(), location); hologram = new HologramImpl(propertyRegistry, configManager, packetFactory, textSerializer, location.withY(location.getY() + type.getHologramOffset())); } public void setType(NpcTypeImpl type) { UNSAFE_hideAll(); this.type = type; - entity = new PacketEntity(packetFactory, this, type.getType(), entity.getLocation()); + entity = new PacketEntity(packetFactory, this, this, type.getType(), entity.getLocation()); hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); UNSAFE_showAll(); } @@ -85,11 +85,7 @@ public class NpcImpl extends Viewable implements Npc { public void setLocation(NpcLocation location) { this.location = location; - entity.setLocation(location, getViewers()); - if (entity.hasMetadata("ridingVehicle")) { - PacketEntity armorStand = (PacketEntity) entity.getMetadata("ridingVehicle"); - armorStand.setLocation(location.withY(location.getY() - 0.9), getViewers()); - } + entity.setLocation(location); hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java index 98cc382..824ef31 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java @@ -24,4 +24,5 @@ public interface PacketFactory { void sendMetadata(Player player, PacketEntity entity, List data); void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); void sendHandSwing(Player player, PacketEntity entity, boolean offHand); + void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java index 74490ce..e1134f8 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_8PacketFactory.java @@ -153,6 +153,12 @@ public class V1_8PacketFactory implements PacketFactory { sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), Collections.singletonList(equipment))); } + @Override + public void setPassenger(Player player, PacketEntity vehicle, PacketEntity passenger) { + sendPacket(player, new WrapperPlayServerSetPassengers(vehicle.getEntityId(), + passenger == null ? new int[] {} : new int[] {passenger.getEntityId()})); + } + protected void sendPacket(Player player, PacketWrapper packet) { packetEvents.getPlayerManager().sendPacket(player, packet); }