remove metadata and add direct vehicle support to PacketEntity

This commit is contained in:
Pyrbu 2024-12-13 01:37:53 +01:00
parent f8d5700b9a
commit aed6ee178c
10 changed files with 85 additions and 105 deletions

View file

@ -16,11 +16,11 @@ import java.util.Set;
* This entity is used to make the NPC sit on an invisible armor stand.
* </p>
*/
public class ArmorStandVehicleEntity implements PropertyHolder {
public class ArmorStandVehicleProperties implements PropertyHolder {
private final Map<EntityPropertyImpl<?>, 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);

View file

@ -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<String, Object> 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<Player> 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<EntityProperty<?>> 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> T getMetadata(String key, Class<T> 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();
}
}

View file

@ -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<Boolean> {
@Override
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> 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);
}
}
}

View file

@ -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;
}
}

View file

@ -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<ItemStack> {
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<ItemStack> {
}
@Override
public void setLocation(NpcLocation location, Collection<Player> 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) {

View file

@ -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<M> implements PropertyHolder {
private final PacketEntity entity;
private final Set<EntityProperty<?>> 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<M> implements PropertyHolder {
entity.despawn(player);
}
public void setLocation(NpcLocation location, Collection<Player> viewers) {
entity.setLocation(location, viewers);
public void setLocation(NpcLocation location) {
entity.setLocation(location);
}
public int getEntityId() {

View file

@ -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<Component> {
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"));
}

View file

@ -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()));
}

View file

@ -24,4 +24,5 @@ public interface PacketFactory {
void sendMetadata(Player player, PacketEntity entity, List<EntityData> 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);
}

View file

@ -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);
}